c ++ rvalue передается константной ссылке - PullRequest
2 голосов
/ 25 июня 2010

Я пытаюсь понять точное поведение C ++ (до C ++ 0x) в отношении ссылок и значений.Является ли следующее действительным?

void someFunc ( const MyType & val ) { 
    //do a lot of stuff
    doSthWithValue ( val);
} 

MyType creatorFunc ( ) { 
    return MyType ( "some initialization value" ); 
} 

int main () { 
    someFunc ( creatorFunc() ); 
    return 0; 
}

Я нашел похожий код в библиотеке, которую я пытаюсь изменить.Я обнаружил, что код вылетает в Visual Studio 2005.
Как я понимаю выше, происходит следующее:
creatorFunc возвращает значение, поэтому создается временный объект MyType obj1.(и хранится ... в стеке?) someFunc получает ссылку на этот временный объект, и в процессе вычислений временный объект перезаписывается / освобождается.
Теперь ошеломляет то, что код чаще всего работает нормально.Более того, с помощью простого куска кода я не могу воспроизвести сбой.
Что здесь происходит / должно происходить?Имеет ли значение, является ли ссылка (val) постоянной или нет?Какова продолжительность жизни объекта, возвращенного от creatorFunc?

Ответы [ 6 ]

4 голосов
/ 25 июня 2010

Возвращаемое значение имеет временное время жизни.В C ++ это означает полное выражение, создавшее тип, поэтому деструктор MyType не должен вызываться до тех пор, пока не вернется вызов someFunc.

Мне любопытно, что вы перезаписаны / освобожденыКонечно, вызов delete для этого объекта не является нормальным;он живет в стеке, и его удаление, вероятно, приведет к повреждению кучи.Кроме того, перезапись / изменение может также быть плохим.В вашем примере используется константа "C string";во многих компиляторах значения, подобные этому, хранятся в постоянной памяти, поэтому попытка изменить ее позже может привести к сбою / нарушению доступа.(Однако я не уверен, что Visual C ++ выполняет эту оптимизацию).

Существует большая разница между передачей временных константных и изменяемых ссылок.Создание изменяемой ссылки на временное не разрешено стандартным C ++, и большинство компиляторов (включая GCC) отклонят его, хотя по крайней мере некоторые версии Visual C ++ допускают это.

Если вы передаете его сИзменяемая ссылка, которую вы хотите написать:

   MyType t = creatorFunc();
   someFunc(t);
3 голосов
/ 25 июня 2010

Срок действия временного объекта, созданного creatorFunc(), до конца вызова someFunc.По сути, следующая точка последовательности (в общем, точка с запятой).

someFunc получает ссылку на этот временный объект, и в процессе вычислений временный объект перезаписывается / освобождается "

Звучит так, будто someFunc совершает «плохие поступки». Вы не должны перезаписывать или освобождать объект, который передается const&.

1 голос
/ 25 июня 2010

Обычно временный объект (такой как объект, возвращаемый вызовом функции) имеет время жизни, которое продолжается до конца "включающего выражения". Тем не менее, временная привязка к ссылке, как правило, имеет время жизни, повышенное до времени жизни ссылки.

Таким образом, временное передаваемое в someFunc() должно оставаться живым и доступным до тех пор, пока не вернется someFunc(). Однако, если someFunc() (или как бы он ни вызывал, например doSthWithValue()), скрывает указатель или ссылку на val, например, в коллекции или каком-либо другом объекте, для использования в более позднее время, временный объект больше не будет жив, и вы, вероятно, потерпите крах, пытаясь использовать его. Возможно, именно поэтому вы не видите сбоев в простом коде со ссылкой на временный код, в то время как более сложный код вылетает.

Для получения более подробной информации см. Следующие пункты:

возвращаемое значение (не ссылка) из функции, привязанное к константной ссылке в вызывающей функции; как его время жизни увеличивается до объема вызывающей функции? C ++ постоянное время жизни ссылки (контейнерный адаптер)

Также обратите внимание, что стандарт позволяет привязывать временные файлы только к константным ссылкам, но, как Джек Ллойд упоминал о некоторых версиях MSVC (до VS 2003 в соответствии с http://msdn.microsoft.com/en-us/library/cfbk5ddc.aspx) разрешалось связывать их с неконстантными ссылками Однако при быстром тестировании я обнаружил, что компилятор VS 2010 все еще позволяет временным привязкам связываться с неконстантными ссылками.

0 голосов
/ 25 июня 2010

У меня была такая же проблема, и когда я прокомментировал как таковой, SO забили, что упомянули об этом раньше.Я чувствую себя оправданным, что у кого-то еще есть эта проблема !!

Я также все еще использую VS 2005 (SP1), возможно какая-то ошибка оптимизации компилятора?чтобы остаться в живых для вызова someFunc ( creatorFunc() ); единственное, что я обнаружил, это разделил его на 2 строки, удалив временную переменную.

0 голосов
/ 25 июня 2010

Да, важно, что ссылка постоянная.Вы не можете связать временные ссылки с неконстантными ссылками, поэтому код не скомпилируется иначе.

Кроме того, ваш код четко определен и будет работать как положено.

0 голосов
/ 25 июня 2010

Вы можете привязать только временную ссылку к константной ссылке.

...