复制省略是几乎所有编译器都支持的允许优化。
复制省略意味着在某些情况下,创建一个临时副本,然后将该临时副本复制到一个命名变量中,然后销毁该临时副本,可能会导致直接构造该变量。
与返回值优化和移动语义一起,意味着返回可移动的复杂对象是高效的。对于像int 这样的类型,as-if 规则也在运行中:编译器可以做任何表现得好像代码行或代码块被执行的事情,并且编译器了解当您复制/移动 @987654322 时会发生什么@ around(即,基本上什么都没有),所以他们可以跳过那些复制/移动。
为确保 RVO 和复制省略正确发生,您需要执行以下操作:
int function() {
int retval = 8; // create the return value in one spot, this makes NRVO possible
// code goes here
return retval; // you can have more than one return statement in most compilers
}
int result = function(); // initialize the variable result by assigning the return value of the function to it.
如果您执行上述操作,大多数编译器将直接在result 变量存储中构造retval 对象,如果function 的主体可以在result 中看到,则根本不会发生任何副本(有些可能即使你看不到function mayhap 的身体,也要这样做)
在 C++11 中还有其他技巧。
int function() {
return {7}; // guaranteed to directly construct the return value without a copy
}
int result = function(); // even if copy elision is not done, the temporary `int` is moved into `result`.
如果你阻止复制省略:
int function() {
int foo = 7;
int bar = 3;
// code
if (foo>bar)
return foo;
else
return bar;
}
只要您返回一个局部变量,就会发生隐式移动。也可以显式地将std::move 放入返回值中。
现在,对于像int 这样简单而小型的类型,所有这些优化都毫无意义。当您处理更大、更昂贵的对象时,例如std::vectors 中的std::vector,每个对象中都有 10 MB 的数据,这些技术意味着按值返回最终与传递指向的指针一样有效小心填写。