移动构造函数
C++03 性能上被长期被诟病的其中之一,就是其耗时且不必要的深度拷贝。深度拷贝会发生在当对象是以传值的方式传递。举例而言,std::vector<T> 是内部保存了C-style 数组的一个包装,如果一个std::vector<T>的临时对象被建构或是从函数返回,要将其存储只能通过生成新的std::vector<T>并且把该临时对象所有的数据复制进去。该临时对象和其拥有的内存会被摧毁。
而有了右值引用后,就可以直接使用右值引用的指针值,无需再重新分配内存和拷贝了。
这里,举一个赋值构造函数和移动构造函数的例子。Person类有三个构造函数,定义如下。
class Person { public: Person(int p) { num = new int; *num = p; }; Person(Person& rhs) ;//赋值构造函数 Person(Person&& rhs) ;//移动构造函数 ~Person() { if (num) { delete num; } }; private: int *num = NULL; };
赋值构造函数,使用深度拷贝进行赋值。
Person::Person(Person& rhs) { cout << "copy constructor" << endl; if (num) { delete num; } num = new int; *num = *rhs.num; }
右值引用定义为T&&,这样我们可以把右值的内存直接拿过来而不需要重新申请内存。在将右值引用rhs的指针num赋值给当前实例后,需要将右值引用的指针num赋值为nullptr,这样离开当前作用域后右值引用的num指针就不会被释放。这样就有效的减少了深度拷贝导致的内存与效率浪费。
Person::Person(Person&& rhs) { cout << "move copy constructor" << endl; if (this != &rhs) { if (num) { delete num; } num = rhs.num; rhs.num = nullptr;//这样rhs析构的时候不会释放num } }
实际应用如下,Person(4)作为一个右值引用初始化p3,有效的减少了深度拷贝造成的资源浪费。
void testPerson() { Person p1(3); Person p2(p1); Person p3(Person(4)); Sleep(0); }
水滴石穿
posted on 2017-11-15 18:04 SpartacusIn21 阅读(369) 评论(0) 编辑 收藏 举报