拷贝省略
大多数编译器都会实现拷贝省略来避免多余的数据拷贝。即在特定情况下会省略类的拷贝/移动构造函数,即使有副作用。这种情况下,编译器会把源和省略的拷贝/移动构造函数看作同一object的两种表示方式(实际上应该是两个object),当后续两个object都销毁时,才会调用析构函数。
例如对于以下代码:
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C();
}
int main() {
std::cout << "Hello World!\n";
C obj = f();
}
以下输出都是有效的:
Hello World!
A copy was made.
A copy was made.
Hello World!
A copy was made.
Hello World!
完整的拷贝应该是将C()拷贝给f()的临时返回值,在将f()的临时返回值拷贝给obj。
而输出2、3则省略了其中的一种和两种拷贝过程。
返回值优化
返回值优化是拷贝省略的一种实现方式,通常有以下几种方式:
命名的返回值优化
class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
};
Thing f() {
Thing t;
return t;
}
Thing t2 = f();
返回临时值
class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
};
Thing f() {
return Thing();
}
Thing t2 = f();
临时值作为参数
class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
};
void foo(Thing t);
foo(Thing());
抛出异常
struct Thing{
Thing();
Thing(const Thing&);
};
void foo() {
Thing c;
throw c;
}
int main() {
try {
foo();
}
catch(Thing c) {
}
}