临时对象 (Temporary objects)
文章内容是阅读 ISO/IEC 14882:2014 12.2节的笔记。
考虑下面的代码
class X {
public:
X(int){ cout << "X Construct" << endl; }
X(const X& other){ cout << "X Copy Construct" << endl; }
X& operator=(const X&){ cout << "X assign Construct" << endl; }
~X(){}
};
class Y {
public:
Y(int){ cout << "Y Construct" << endl; }
Y(Y&&){ cout << "Move Construct" << endl; }
~Y(){}
};
X f(X){}
Y g(Y){}
void h() {
X a(1);
X b = f(X(2));
Y c = g(Y(3));
a = f(a);
}
int main(){
h();
}
笔者在 g++6.2 下编译并运行以上代码的结果
X Construct
X Construct
Y Construct
X Copy Construct
X assign Construct
可以把 f() 的使用的 X(2) 临时对象优化为一个构造函数调用,将拷贝/移动构造函数的调用优化没。
再考虑以下代码
#include <iostream>
#include <utility>
#include <string>
using namespace std;
class B{
public:
B():__var(){ cout << "B Construct" << endl; }
B(B const& other){ std::cout << "Copy Construct" << std::endl; }
B(B&& other):__var( std::move(other.__var) ){ std::cout << "B Move Construct" << std::endl; }
~B(){ std::cout << "B Destory" << std::endl; }
std::string __var;
};
B func(){
B _var;
_var.__var = "Hello World";
return _var;
}
auto v = func();
对于以上代码,C++14标准条款12.8第31条指出:
Here the criteria for elision can be combined to eliminate two calls to the copy constructor of class
这意味着,函数func中的局部变量 _var 的内存地址可以是调用域中 v
的地址。也就是说,这样就避免了 _var 的构造、2次拷贝构造的函数调用(也可以理解为避免了两个临时对象的构造).
如果一个class type的临时对象有一个有效的构造函数和析构函数,那么一定会被调用。析构函数则在表达式(full-expression)最后执行。