Rvalue to lvalue conversion Visual Studio
В Visual Studio 2012RC есть несколько нестандартных расширений. Например, этот код компилируется:
#include <string>
using namespace std;
void value(string& value)
{
value = "some";
}
int main()
{
value(string("nice"));
}
и получите предупреждение о том, что это нестандартное расширение. Итак, я хочу понять, как это реально и как преобразуются коды (rvalue-reference или const ссылка с const_cast)?
Ответы
Ответ 1
Временным объектом типа класса по-прежнему является объект. Он живет где-то в памяти, а это означает, что в компиляторе нет ничего необычного, чтобы прикрепить ссылку на него. На физическом уровне, независимо от того, является ли это константной ссылкой или неконстантной ссылкой, нет никакой разницы. Другими словами, в таких случаях ограничение языка является чисто концептуальным, искусственным. Компилятор просто игнорирует это ограничение. Здесь нет необходимости "трансформировать" что-либо. Ссылка просто привязана непосредственно к объекту, где бы он ни находился.
В принципе, для класса, который предоставляет внешнему слову доступ к значению его указателя this
(или с lvalue-доступом к *this
), поведение может быть немедленно и легко смоделировано
struct S {
S& get_lvalue() { return *this; }
};
void foo(S& s);
...
foo(S().get_lvalue());
Вышеприведенный код совершенно легален и работает вокруг вышеупомянутого ограничения. Вы можете думать, что поведение MSVС++ эквивалентно этому.
Ответ 2
В принципе, VS будет выделять пространство где-то и просто дать ссылку на него, как если бы это была ссылка-to- const
без константы (или в С++ 11 ссылка rvalue).
Вы можете отключить это поведение с помощью компилятора /Za
(отключить расширение языка) в
Свойства → C/С++ → Язык
Если я правильно помню.
Ответ 3
В стандартном С++ вы не можете привязать временную (rvalue/ string("nice")
) к неконстантной ссылке (lvalue), но это позволяет компилятор microsoft. Предупреждение сообщает вам, что код компилируется из-за расширения и не будет компилироваться с любым другим компилятором.