请考虑以下代码.调用doStuff()但未使用返回值时会发生什么?SomeClass还在创建吗?当然,创建本身可能会产生重要的副作用,但复制构造函数也是如此,它们在RVO/copy-elision中仍然被省略.
SomeClass doStuff(){
//...do stuff
return SomeClass( /**/);
}
SomeClass some_object = doStuff();
doStuff(); //What happens here?
Run Code Online (Sandbox Code Playgroud)
(编辑:用GCC -O3对此进行测试.构造对象然后立即销毁)
Sto*_*ica 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.
Run Code Online (Sandbox Code Playgroud)
在某些情况下,编译器可能会删除不必要的副本,即使它有副作用,是的.
如果对象具有副作用,编译器可能不会忽略对象的整个存在.
如果它没有副作用,那么就没有可观察到的结果,因此存在是否发生实际上是一个非问题.
tl;博士:标准列出了非常具体的省略机会,而这不是其中之一.