2016-05-29 2 views
2

В следующем примере:C++ расширение жизни &&

http://coliru.stacked-crooked.com/a/7a1df22bb73f6030

struct D{ 
    int i;  
    auto test2(int&& j){ 
     return [&](){  // captured by reference! 
      cout << i*(j); 
     }; 
    }  
}; 

int main() 
{ 
    D d{10}; 
    { 
     auto fn = d.test2(10); 
     fn();      // 1. wrong result here 

     d.test2(10)();   // 2. but ok here 
    } 
} 

Почему d.test2(10)(); работает?

Должно ли это действительно работать, или это только мое неопределенное поведение равно правильному результату?

P.S. После прочтения this Я вижу только одно объяснение: в (2) временное время жизни продлевается до конца выражения, а вызов происходит в том же выражении с & & crteation; в то время как (1) на самом деле состоит из 2-х выражений:

временной границы с опорным параметром при вызове функции существует до конца полного выражения, содержащего этот вызов функции: если функция возвращает ссылку, которая переживает полное выражение, становится болтливой ссылкой.

В этом случае?

+3

Да, ответ, который вы нашли и поставил на ваш вопрос, является правильным ответом. – hvd

+0

@hvd - Вы уверены? На самом деле я не могу найти опровержение «выражения». – tower120

+0

Да, конечно. «Выражение» - это произведение в грамматике. «Полное выражение» определено в [intro.execution] p10 и в основном означает «выражение, которое не является подвыражением», что означает единственное полное выражение в 'd.test2 (10)();' statement is 'd .test2 (10)() '. – hvd

ответ

4

Временный объект длится до конца строки (ну, полное выражение), где он создан, если не продлевается срок его службы.

Ваш код не продлевает срок службы любых временных рядов. Продление срока службы через привязку к ссылкам не «коммутирует», только первое связывание продлевает срок службы.

Таким образом, самый старый случай - это UB, поскольку у вас есть оборванная ссылка. Указанное временное уходит конец конца строки: на следующей строке вы следуете ссылке, а хаос hapens.

Во втором случае ваша ссылка не продлевает срок службы временного, но временное длится дольше, чем ссылка, которая связывается с ней! Они оба умирают в конце линии, в обратном порядке строительства.

Таким образом, звонок работает.

+3

by * line * вы имеете в виду * полное выражение * - возможно, что на одной строке курсора имеется несколько операторов. –

+0

@ M.M да, кто-то может сгруппировать кучу ';' разделимых полных выражений вместе. :) И полное выражение может охватывать более одной строки. – Yakk

+0

@Yakk: Знаете ли вы ссылку в стандарте, почему «продление срока службы через привязку к ссылкам не« коммутирует »? Или, может быть, лучше, эвристическое объяснение, чтобы помочь запомнить и объяснить, почему это так? –

-1

Должно ли это действительно работать, или это только мое неопределенное поведение равно правильному результату?

Похоже на это. В данном примере вы связаны, у вас есть эти предупреждения:

warning: '<anonymous>' is used uninitialized in this function [-Wuninitialized] 

Неинициализированные объекты имеют indetermine значения, и пытаются получить доступ к этим значению результатов в непредсказуемом поведении.

+0

Только некоторые версии gcc бросают его. clang не генерирует никаких предупреждений вообще. – tower120

+0

Извините, но вы неправильно читаете предупреждения. Если вы закомментируете вызовы, которые OP уже отметил как неработающие, вы обнаружите, что GCC не дает никаких предупреждений, и это правильно. – hvd

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