Ссылка на r-значение (адрес r-значения)

Предположим, у нас есть функция, которая возвращает значение:

int func() {
int x = 10; // create local variable x with value of 5
return x;  // create temporary copy of x which is returned, local variable x is destroyed
}

int main()
{
int y = func(); // temporary copy of x is copied to y, when it hits`;` the temporary object is destroyed
return 0;
}

Поправьте меня, если я ошибаюсь в чем-то, что я сказал в комментариях выше.

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

int main()
{
const int & y = func();  // now the temporary object (R-value) is not destroyed when it hits `;` thus the life time is lenghtened.
return 0;
}

Вопрос в том, что поскольку я создал постоянную ссылку на временный объект, который должен быть уничтожен, означает ли это, что cout << &y << endl будет печатать адрес этого временного объекта, так как ссылка это просто «псевдоним»? Также, где эти временные объекты (R-значения) хранятся в памяти (я использовал примитивный тип int, но это может быть класс)?

2

Решение

Как уже указывалось в комментариях, создание ссылки на const (или ссылку на rvalue) на временную ссылку продлевает срок ее службы до той, что указана для ссылки.

Также, где эти временные объекты (R-значения) хранятся в памяти (я
использовал примитивный тип int, но это может быть класс)?

Это не указано в стандарте. Тем не менее, вы можете просто проверить наиболее распространенные компиляторы, что они будут делать. Начиная с GCC, без каких-либо оптимизаций, вы получите

func():
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 10
mov eax, DWORD PTR [rbp-4]
pop rbp
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16
call func()
mov DWORD PTR [rbp-12], eax
lea rax, [rbp-12]
mov QWORD PTR [rbp-8], rax
mov eax, 0
leave
ret

https://godbolt.org/g/8wPQqx

Таким образом, возвращаемое значение помещается в регистр EAX внутри функции, и как только оно возвращается, значение помещается в кадр стека main (), как если бы вы создали переменную в функции main. Вы найдете похожие результаты с другими компиляторами. При включении оптимизаций, очевидно, произойдет очевидное: компилятор видит, что функция просто возвращает некоторое постоянное значение и полностью его исключает:

func():
mov eax, 10
ret
.LC0:
.string "%i"main:
sub rsp, 24
mov edi, OFFSET FLAT:.LC0
xor eax, eax
lea rsi, [rsp+12]
mov DWORD PTR [rsp+12], 10
call printf
xor eax, eax
add rsp, 24
ret

Здесь я добавил несколько вызовов printf (), которые выведут адрес временного s.t. программа не совсем тривиальна.
Таким образом, он создает функцию, но не будет вызывать ее и просто записывает 10 снова в некоторое пространство в кадре локального стека. Если вы просто используете его по значению, он будет просто внесен в регистр, так как адрес не требуется.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]