详解C++中对构造函数和赋值运算符的复制和移动操作

2020-01-06 14:26:07于海丽

以下示例演示移动语义如何能提高应用程序的性能。此示例将两个元素添加到一个矢量对象,然后在两个现有元素之间插入一个新元素。在 Visual C++ 2010 中,vector 类使用移动语义,通过移动矢量元素(而非复制它们)来高效地执行插入操作。


// rvalue-references-move-semantics.cpp
// compile with: /EHsc
#include "MemoryBlock.h"
#include <vector>

using namespace std;

int main()
{
 // Create a vector object and add a few elements to it.
 vector<MemoryBlock> v;
 v.push_back(MemoryBlock(25));
 v.push_back(MemoryBlock(75));

 // Insert a new element into the second position of the vector.
 v.insert(v.begin() + 1, MemoryBlock(50));
}

 

该示例产生下面的输出:


In MemoryBlock(size_t). length = 25.
In MemoryBlock(MemoryBlock&&). length = 25. Moving resource.
In ~MemoryBlock(). length = 0.
In MemoryBlock(size_t). length = 75.
In MemoryBlock(MemoryBlock&&). length = 25. Moving resource.
In ~MemoryBlock(). length = 0.
In MemoryBlock(MemoryBlock&&). length = 75. Moving resource.
In ~MemoryBlock(). length = 0.
In MemoryBlock(size_t). length = 50.
In MemoryBlock(MemoryBlock&&). length = 50. Moving resource.
In MemoryBlock(MemoryBlock&&). length = 50. Moving resource.
In operator=(MemoryBlock&&). length = 75.
In operator=(MemoryBlock&&). length = 50.
In ~MemoryBlock(). length = 0.
In ~MemoryBlock(). length = 0.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 50. Deleting resource.
In ~MemoryBlock(). length = 75. Deleting resource.

使用移动语义的此示例版本比不使用移动语义的版本更高效,因为前者执行的复制、内存分配和内存释放操作更少。
可靠编程
若要防止资源泄漏,请始终释放移动赋值运算符中的资源(如内存、文件句柄和套接字)。
若要防止不可恢复的资源损坏,请正确处理移动赋值运算符中的自我赋值。
如果为您的类同时提供了移动构造函数和移动赋值运算符,则可以编写移动构造函数来调用移动赋值运算符,从而消除冗余代码。以下示例显示了调用移动赋值运算符的移动构造函数的修改后的版本:


// Move constructor.
MemoryBlock(MemoryBlock&& other)
 : _data(nullptr)
 , _length(0)
{
 *this = std::move(other);
}


注:相关教程知识阅读请移步到C++教程频道。