从函数返回的对象是否在未使用时仍然创建?

时间:2018-02-14 08:26:22

标签: c++ lifetime

请考虑以下代码。调用doStuff()但未使用返回值时会发生什么? SomeClass还在创建吗?当然,创建本身可能会产生重要的副作用,但复制构造函数也是如此,它们在RVO / copy-elision中仍然被省略。

SomeClass doStuff(){
    //...do stuff
    return SomeClass( /**/);
}

SomeClass some_object = doStuff();
doStuff(); //What happens here?

(编辑:用GCC -O3对此进行测试。对象构建然后立即被破坏)

2 个答案:

答案 0 :(得分:22)

对于RVO和复制省,我觉得有一个误解。这并不意味着不创建函数的返回值。它始终是创建的,这不是实现可以做的事情。

唯一的余地是,尽管存在副作用,但是在复制副本时,还是要削减中间人。使用调用结果初始化对象时,标准允许插入目标对象,以便函数直接初始化。

如果您没有提供目标对象(通过使用结果),则必须实现并销毁临时对象,作为包含函数调用的完整表达式的一部分。

所以要举一点你的例子:

doStuff(); // An object is created and destroyed as part of temporary materialization
           // Depending on the compilers analysis under the as-if rule, there may be
           // further optimization which gets rid of it all. But there is an object there 
           // formally.

std::rand() && (doStuff(), std::rand());
// Depending on the result of std::rand(), this may or may not create an object.
// If the left sub-expression evaluates to a falsy value, no result object is materialized.
// Otherwise, one is materialized before the second call to std::rand() and 
// destroyed after it.

答案 1 :(得分:6)

编译者可能会在某些情况下忽略不必要的副本,即使它有副作用,是的。

编译器可能忽略对象的整个存在,如果它有副作用。

如果没有副作用,则无法观察到结果,因此是否存在是否存在实际上是一个无问题。

tl; dr:该标准列出了非常具体的省略机会,而这不是其中之一。