C++移动构造函数

对于了解移动构造函数的工作原理,我们需要在编译时设置编译选项-fno-elide-constructors以关闭返回值优化效果,从样就可以看到完整的移动构造函数调用过程,避免编译器优化,有些地方看不到调用移动构造函数的过程。-fno-elide-constructors这个参数只是针对C++的,手册对该参数的描述如下:

   -fno-elide-constructors
       The C++ standard allows an implementation to omit creating a
       temporary which is only used to initialize another object of the
       same type.  Specifying this option disables that optimization, and
       forces G++ to call the copy constructor in all cases.

大致意思是:C++标准允许一种(编译器)实现省略创建一个只是为了初始化另一个同类型对象的临时对象。指定这个参数(-fno-elide-constructors)将关闭这种优化,强制G++在所有情况下调用拷贝构造函数。

(在stackoverflow上有一个有关这个参数使用的问题https://stackoverflow.com/questions/27086573/when-and-why-would-i-use-fno-elide-constructors

下面就一段代码进行分析。

<textarea readonly="readonly" name="code" class="c++"> 
class A
{
public:
	A() :m_ptr(new int(0)) { cout << "construct" << endl; }

	A(const A& a) :m_ptr(new int(*a.m_ptr)) //深拷贝的拷贝构造函数
	{
		cout << "copy construct" << endl;
	}

	A(A&& a) :m_ptr(a.m_ptr)
	{
		a.m_ptr = nullptr;
		cout << "move construct" << endl;
	}

	~A()
	{
		cout << "delete " << endl;
		delete m_ptr;
	}
private:
	int* m_ptr;
};

A GetA()
{
	A b;
	return b;
}


int main() {

	A a = GetA();

	system("pause");
	return 0;
}
</textarea>

使用g++ test.cpp -fno-elide-constructors -g -o .\.output\main.exe命令进行编译

运行结果:

construct      //这是A b时调用无参构造函数
move construct     //这是b初始化函数返回的临时对象时调用的移动构造函数
delete       //释放b对象
move construct  //将函数返回的临时对象初始化a时调用移动构造函数
delete  //释放a对象

当将移动构造函数注释掉,编译后运行结果为:

construct    /这是A b时调用无参构造函数
copy construct    //这是b初始化函数返回的临时对象时调用的拷贝构造函数
delete    //释放b对象
copy construct    //将函数返回的临时对象初始化a时调用拷贝构造函数(因为自定义了拷贝构造函数,因此编译器不会合成默认   移动构造函数)
delete   //释放掉函数返回的临时对象

当将移动构造函数和拷贝构造函数都注释掉,编译后运行结果为:

construct  //这是A b时调用无参构造函数
delete      //释放b对象
delete   //释放掉函数返回的临时对象

注意第三种情况使用的是编译器自己合成的拷贝构造函数。因为没有自己定义拷贝构造函数或者拷贝赋值运算符。这里由于自定义了析构函数,因此编译器不会合成默认的移动构造函数。具体的可以参考《C++ primer》第13章。

猜你喜欢

转载自blog.csdn.net/J_H_C/article/details/82290228