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  //释放函数返回的临时对象

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

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

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

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

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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
移动构造函数C++11引入的一个新特性,通过移动构造函数,可以将一个对象的资源所有权转移到另一个对象,避免了不必要的资源拷贝,提高了程序的运行效率。 移动构造函数的定义如下: ```cpp class ClassA { public: ClassA(ClassA&& other) noexcept { // 移动构造函数的实现 } }; ``` 其中,`ClassA&&`表示移动构造函数的参数为右值引用。移动构造函数通常使用`noexcept`关键字进行修饰,表示该函数不会抛出异常。 移动构造函数的实现需要将另一个对象的资源转移到当前对象,并将另一个对象的资源置为无效。常见的实现方式是通过移动构造函数中的`std::move()`函数来完成。例如,对于一个包含动态分配内存的类: ```cpp class MyClass { public: MyClass(int n) : data(new int[n]), size(n) {} MyClass(MyClass&& other) noexcept : data(other.data), size(other.size) { other.data = nullptr; other.size = 0; } ~MyClass() { delete[] data; } private: int* data; int size; }; ``` 在移动构造函数中,将另一个对象的指针和大小赋值给当前对象,并将另一个对象的指针置为nullptr,大小置为0,表示另一个对象的资源已经被移动到了当前对象。 使用移动构造函数可以大大提高程序的性能,特别是在涉及到大量的资源拷贝时。移动构造函数可以通过`std::move()`函数进行调用,例如: ```cpp MyClass a(10); MyClass b(std::move(a)); // 调用移动构造函数 ``` 在这个例子中,对象a的资源被移动到了对象b中,对象a的资源已经无效了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值