c ++ rvalue传递给const引用

时间:2010-06-25 15:47:15

标签: c++ visual-studio-2005 pass-by-reference

我正在尝试了解有关引用和rvalues的确切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)是const,那有关系吗?从creatorFunc返回的对象的生命周期是什么?

6 个答案:

答案 0 :(得分:4)

返回值具有临时的生命周期。在C ++中,这意味着创建该类型的完整表达式,因此在调用someFunc返回之前,不应调用MyType的析构函数。

我很好奇你的'被覆盖/被释放'。当然在这个对象上调用delete是不行的;它存在于堆栈中并删除它可能会导致堆损坏。此外,覆盖/修改它也可能是坏事。您的示例使用常量“C字符串”;在许多编译器上,这样的值存储在只读内存中,因此稍后尝试修改它可能会导致崩溃/访问冲突。 (但我不确定Visual C ++是否会进行此优化)。

通过const传递临时值与可变引用之间存在很大差异。标准C ++不允许创建对临时文件的可变引用,并且大多数编译器(包括GCC)都会拒绝它,尽管至少某些版本的Visual C ++允许它。

如果您使用可变引用传递它,您要写的是:

   MyType t = creatorFunc();
   someFunc(t);

答案 1 :(得分:3)

creatorFunc()创建的临时文件的生命周期一直持续到someFunc调用结束。实际上,下一个序列点(松散地,分号)。

  

someFunc正在引用该临时对象,随着计算的进行,临时对象被覆盖/释放“

听起来someFunc正在做“坏事”。您不应该覆盖或释放由const&传递的对象。

答案 2 :(得分:1)

通常,临时对象(例如函数调用返回的对象)的生命周期延伸到“封闭表达式”的末尾。但是,对引用的临时绑定通常会将其生命周期“提升”到引用的生命周期。

因此传递给someFunc()的临时值应该保持活动状态并且可以在someFunc()返回之后访问。但是,如果someFunc()(或其可能调用的任何内容,例如doSthWithValue())将指针或引用存储到val,例如在集合或其他对象中,则用于某些稍后,临时对象将不再存在,您可能会在尝试使用它时崩溃。这可能就是为什么你看到简单的代码没有崩溃,引用一个临时的,而更复杂的代码崩溃。

有关详细信息,请参阅以下项目:

return value (not a reference) from the function, bound to a const reference in the calling function; how is its lifetime extended to the scope of the calling function? C++ constant reference lifetime (container adaptor)

另请注意,该标准允许temporaries仅绑定到const引用,但正如Jack Lloyd提到的某些版本的MSVC(根据http://msdn.microsoft.com/en-us/library/cfbk5ddc.aspx在VS 2003之前)允许您将它们绑定到非const引用。但是,在快速测试中,我发现VS 2010的编译器仍然允许临时值绑定到非const引用。

答案 3 :(得分:0)

您只能将临时绑定到const引用。

答案 4 :(得分:0)

是的,重要的是引用是const。您不能将临时绑定到非const引用,因此代码将无法编译。

除此之外,您的代码定义明确,并且可以按预期工作。

答案 5 :(得分:0)

我遇到了同样的问题,当我在SO上发表评论的时候因为之前提到它而受到重创。我觉得其他人有这个问题的证据!!

我还在使用VS 2005(SP1),也许还有一些编译器优化错误?

来自creatorFunc()的结果似乎没有为调用someFunc ( creatorFunc() );保持活着,我发现唯一要做的就是将其拆分为2行,从而删除临时变量。