2013-07-21 5 views
4

Видимо есть какая-то путаница и различие между составителями в отношении этого вопроса:Срок службы xvalue привязан к ссылке расширенной или нет?

http://social.msdn.microsoft.com/Forums/vstudio/en-US/3c754c4e-5471-4095-afae-795c1f411612/rvalue-refs-extended-lifetime-inconsistent-with-gccstandard

Согласно этому сообщению:

What are rvalues, lvalues, xvalues, glvalues, and prvalues?

Xvalues ​​является rvalues ​​(наряду с prvalues) и стандарт говорит:

Второй контекст - это ссылка на bo и временно. временно, к которому ссылка привязана или временное, что является полным объектом подобъекта, к которому ссылка привязана сохраняется в течение всего срока ссылки, за исключением:

Однако существует сообщения, которые оспаривали :

Do rvalue references allow dangling references?

What is an example of a difference in allowed usage or behavior between an xvalue and a prvalue FOR NON-POD objects?

Может кто-то пожалуйста, прояснить этот вопрос. Правильно ли MSVC?

ответ

3

Xvalues ​​может быть rvalues, но это не значит, что они являются временными. Продление времени жизни связано с тем, что они являются временными, а не их ценовой категорией.

Я намеренно стараюсь не знать порядок обработки операторов (таким образом, я заставляю себя писать код, который либо использует явные скобки, либо не заботится о заказе). Ваш конкретный adder пример кода, воспроизведенный здесь, делает уход:

template <class T> 
struct addable 
{ 
    friend T operator +(const T& lhs, const T& rhs) 
    { 
     return std::move(T(lhs) += rhs); 
    } 
    friend T operator +(const T& lhs, T&& rhs) 
    { 
     return std::move(T(lhs) += std::move(rhs)); 
    } 
    friend T&& operator +(T&& lhs, const T& rhs) 
    { 
     return std::move(lhs += rhs); 
    }    
    friend T&& operator +(T&& lhs, T&& rhs) 
    { 
     return std::move(lhs += std::move(rhs)); 
    } 
}; 

Если оператор + выполняется справа налево, затем t1 + t2 + t3 будет работать в t1 + (t2 + t3). t2 + t3 вызовет первую перегрузку, создав таким образом временной, таким образом получив t1 + temp. Так как временный предпочтительнее связывается с ссылкой на r-значение, это выражение вызовет вторую перегрузку, которая будет также возвращает временную.

Однако, если оператор + работает слева направо, вы получаете (t1 + t2) + t3. Это дает нам temp + t1, что вызывает проблему. Это вызовет третью перегрузку. Параметр lhs этой функции - это T&&, ссылка на временную. Вы возвращаете ту же ссылку. Это означает, что вы вернули ссылку на временную. Но C++ этого не знает; все, что он знает, это то, что вы возвращаете ссылку на что-то.

Это «что-то», однако, должно быть уничтожено после окончательного выражения (присваивается новая переменная, тип значения или ссылочный тип). Помните: C++ не знает, что эта функция вернет ссылку на ее первый параметр. Таким образом, он не знает, что время жизни временного переданного функциональному операнду должно быть расширено до времени жизни, в котором хранится возвращаемая ссылка.

Кстати, вот почему деревья выражений могут быть опасными с auto и такими скрывающимися. Поскольку созданные внутренние временные записи не могут быть сохранены новыми временными или ссылками, хранящимися в разных объектах. У C++ просто нет способа сделать это.

Итак, кто прав, зависит от того, в каком порядке разрешены операторы. Однако я предпочитаю свое решение: не полагайтесь на эти углы языка и просто обходите их. Прекратите возвращать T&& из этих перегрузок и просто переместите значение во временное. Таким образом, он гарантированно работает правильно, и вам не нужно постоянно проверять стандарт, чтобы убедиться, что ваш код работает.

Кроме того, в качестве стороннего, я бы счел его несколько грубым для оператора + фактически изменить один из параметров.

Однако, если вы настаиваете на том, чтобы знать, кто прав, это GCC. Из раздела 5.7, p1:

Аддитивные операторы + и - группа слева направо.

Да, это не должно работать.

Примечание: Visual Studio позволяет T &r2 = t1 + t2 + t3; компилировать в качестве (очень раздражающего) языкового расширения. Вы, должно быть, получили предупреждение от него.

+0

Я не плакат на сайте M $, просто смущенный. Я даже не использую MSVC, но я беспокоюсь о смысле моего кода. – user1095108

+0

@ user1095108: Я добавил добавление внизу. –

+0

Вы хорошо объяснили, но могли бы вы также указать на соответствующие разделы стандарта? Если я правильно понимаю, что возвращение ссылки rvalue к временному автоматически приводит к оборванной ссылке. – user1095108

Смежные вопросы