Почему я могу взять адрес *v.begin(), где v — это std::vector

#include <vector>
#include <cstdio>
using namespace std;
int f()
{
    int* a = new int(3);
    return *a;
}
int main()
{
    //printf("%p\n", &f()); 
    vector<int> v{3};
    printf("%p\n", &(*(v.begin())));
}

Я не могу взять адрес f(). Если я прокомментирую "printf("%p\n", &f());

*(v.begin()) является первым элементом int в векторе и имеет правильный адрес.
wohlstad 16.02.2023 13:25
*(v.begin()) есть int&. f() есть int.
Mike Vine 16.02.2023 13:27

xiutao 16.02.2023 13:31

@wohlstad, но *a также выделяется в куче с действительным адресом

xiutao 16.02.2023 13:32
f не возвращает объект, выделенный в куче (который фактически просочился). Он возвращает временную копию значения int.
wohlstad 16.02.2023 13:34

Итак, как оператор * std::vector может напрямую возвращать первый элемент? @вольстад

xiutao 16.02.2023 13:37

@DevSolar Эрр, нет. Попробуйте: std::is_same<decltype(*v.begin()), int>::value.

Konrad Rudolph 16.02.2023 13:48

@KonradRudolph Я имел в виду комментарий ОП (один комментарий выше моего), в котором упоминалось, что то, что возвращает f, - «*a также выделяется в куче» (что неверно).

wohlstad 16.02.2023 14:00

@KonradRudolph Я исправлен. В стандарте написано "конвертируемый в Т", и я почему-то мысленно отбросил "конвертируемый в". Ошибка CppReference.com также не помогла. ;-)

DevSolar 16.02.2023 14:20
Конечные и Readonly классы в PHP
Конечные и Readonly классы в PHP
В прошлом, когда вы не хотели, чтобы другие классы расширяли определенный класс, вы могли пометить его как final.
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
Если вы уже умеете работать с React, создание мобильных приложений для iOS и Android - это новое приключение, в котором вы сможете применить свои...
БЭМ: Конвенция об именовании CSS
БЭМ: Конвенция об именовании CSS
Я часто вижу беспорядочный код CSS, особенно если проект большой. Кроме того, я совершал эту ошибку в профессиональных или личных проектах и...
Революционная веб-разработка ServiceNow
Революционная веб-разработка ServiceNow
В быстро развивающемся мире веб-разработки ServiceNow для достижения успеха крайне важно оставаться на вершине последних тенденций и технологий. По...
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Заголовок веб-страницы играет наиболее важную роль в SEO, он помогает поисковой системе понять, о чем ваш сайт.
Конфигурация Jest в angular
Конфигурация Jest в angular
В этой статье я рассказываю обо всех необходимых шагах, которые нужно выполнить при настройке jest в angular.
1
9
102
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Функция f возвращает временный объект типа int

int f()
{
    int* a = new int(3);
    return *a;
}

Вы не можете применять адрес оператора для временного объекта.

Вы можете вернуть ссылку на созданный динамически объект, например,

int & f()
{
    int* a = new int(3);
    return *a;
}

И в этом случае этот вызов printf написан как

printf("%p\n", ( void * )&f());

Будет правильно.

Таким образом, правильный ответ должен быть: * оператор вектора возврата по ссылке. Спасибо!

xiutao 16.02.2023 13:42

@xiutao Нет. Пожалуйста.:)

Vlad from Moscow 16.02.2023 13:44

@DevSolar В моем ответе ясно написано, что «оператор разыменования действительно возвращает ссылку на указанный объект итератором». Так что ваш комментарий не имеет смысла. Что касается функции f, то она возвращает ссылку, полученную путем разыменования указателя на динамически размещенный объект в операторе return. Это полная аналогия с разыменованием итератора, возвращаемого функцией begin.

Vlad from Moscow 16.02.2023 13:59

@DevSolar Да, вы правы, v.begin() возвращает vector::iterator. Но это не то, что я хотел знать. Что я вынес из этого ответа, так это то, что оператор разыменования возвращает ссылку.

xiutao 16.02.2023 14:04
Я не могу взять адрес f(), если я прокомментирую "printf("%p\n", &f());


как можно взять адрес *(v.begin())?

С другой стороны, std::vector::begin возвращает итератор к первому элементу вектора (в случае, если вектор не пуст). Затем применение * к v.begin() дает нам тот самый первый элемент (т.е. *(v.begin()) является lvalue), адрес которого мы можем взять.

С другой стороны, f сама возвращает значение — это просто временный объект, у которого нет действительного адреса (по крайней мере, потенциально — значение может быть возвращено, согласно соглашению о вызовах, в стеке, тогда у него есть адрес , а так же в регистре ЦП, то адреса просто нет). Это значение сначала нужно присвоить переменной, чтобы вы действительно могли взять адрес.

Другие вопросы по теме