Законно ли брать адрес ссылки const lvalue?

#include <iostream>
int foo()
{
  return 0;
}

int main()
{
  const int& a = foo();
  std::cout << &a << std::endl;
}

В этом коде a привязывается к rvalue. Законно ли брать его адрес? (И под законным я подразумеваю: в неправильном коде? Я вызываю неопределенное поведение?)


person qdii    schedule 08.11.2012    source источник
comment
Я бы сказал, что это нормально, потому что временное значение существует до тех пор, пока ссылка const, к которой оно привязано, поэтому печать этого адреса должна быть в порядке. Я пока не могу ссылаться на это.   -  person chris    schedule 08.11.2012
comment
@chris: как насчет случаев, когда значение возвращается в регистре, а не в стеке?   -  person qdii    schedule 08.11.2012
comment
Для меня это выглядит как хорошо сформированный код с определенным поведением. Временное, к которому привязана ссылка, или временное, которое является полным объектом подобъекта, к которому привязана ссылка, сохраняется в течение всего времени существования ссылки... Другими словами, в этот момент значение очень похоже на любой другой местный.   -  person Jerry Coffin    schedule 08.11.2012
comment
@qdii, я думал об этом, но когда вы берете адрес, я полагаю, что для этого он должен застрять в памяти. Если подумать, компилятор может поместить любые переменные в регистры, а не хранить их в памяти. Следовательно, это было бы эквивалентно получению адреса любой другой переменной в этом отношении.   -  person chris    schedule 08.11.2012
comment
@qdii: это деталь реализации, к вам не имеющая отношения. Компилятор должен сделать все возможное, чтобы код заработал, и если это означает отказ от использования регистра, пусть будет так.   -  person GManNickG    schedule 08.11.2012


Ответы (2)


Это отлично. В С++ 11 вы даже можете сделать это:

int&& a = foo();
a = 123;

Вы можете думать о временных объектах следующим образом (концептуально и в целом):

x = func(); // translated as:

auto __temporary = func();
x = __temporary;
__destruct_value_now_and_not_later(__temporary);

За исключением случаев, когда x является определением ссылочного типа, компилятор отмечает, что вы намеренно ссылаетесь на временное значение, и продлевает его время жизни, удаляя код раннего уничтожения, превращая его в обычную переменную.

person GManNickG    schedule 08.11.2012
comment
Я полагаю, что время жизни продлевается только для ссылок на константные значения. - person Nemo; 08.11.2012
comment
@GManNickG: Ну, не какая-либо ссылка (например, неконстантная ссылка lvalue), а для &&. - person ildjarn; 08.11.2012
comment
Как это будет реализовано, когда вызываемый объект выделяет место в стеке для переменной, но не освобождает его все в зависимости от того, чему вызывающий присваивает результат? - person Seth Carnegie; 08.11.2012
comment
@SethCarnegie: Извините, я не понимаю. Обратите внимание, что это только обобщение, намеренно опускающее детали; то, как это на самом деле реализовано, не влияет на идею. Как правило, вызывающая сторона отвечает за предоставление места для возвращаемого значения (при условии, что оно не помещается в регистр, который и вызывающая сторона, и вызываемая сторона знают априори). - person GManNickG; 08.11.2012
comment
@GManNickG о, ты прав, я думал о чем-то не относящемся к делу. Вы знаете, в каком разделе стандарта это находится (продление срока службы временных)? - person Seth Carnegie; 08.11.2012

Да. До тех пор, пока переменная a не выйдет за пределы области видимости, временное значение будет действительным. Херб Саттер может объяснить это лучше .

person moswald    schedule 08.11.2012