c++11新引入的这个特性实在是太棒了。因为它避免了对象创建过程中的内存分配问题,所以使代码执行的高效率更高。本文讨论对象移动操作的注意事项。
一个c++类要想支持移动操作必须满足如下条件:
- move之后的原对象必须处于刚初始化的状态(关于初始化与赋值的概念请查阅《effective c++》对于理解这个条件很重要)。
- 销毁移动后的对象必须是安全的(比如:不可出现释放正在使用的资源)
下面代码是一个支持移动操作(移动拷贝、移动赋值)的类A。移动构造函数成员初始化表接管了被移动对象的内存,函数体内将被移动对象设置为初始化状态。
class A {
public:
A(int a) : m_p(nullptr) {
m_p = new int(a);
}
A(const A &ref) {
if (this->m_p == nullptr) {
this->m_p = new int(*ref.m_p);
} else {
*m_p = *ref.m_p;
}
}
A(A &&ref) : m_p(ref.m_p) { // 接管被移动对象的成员内存;
ref.m_p = nullptr; // 销毁移动后的对象必须是安全的;
}
A &operator=(const A &ref) {
if (this != &ref) {
if (this->m_p == nullptr) {
this->m_p = new int(*ref.m_p);
} else {
*m_p = *ref.m_p;
}
}
return *this;
}
A &operator=(A &&ref) {
if (this != &ref) {
if (m_p) {
delete m_p;
m_p = nullptr;
}
this->m_p = ref.m_p;
ref.m_p = nullptr;
}
return *this;
}
~A() {
if (m_p) {
delete m_p;
m_p = nullptr;
}
}
private:
int *m_p;
};
int main(int argc, char** argv)
{
{
A a(90);
A a2 = std::move(a);
A a3(88);
a3 = std::move(a2);
A a4 = a3;
}
getchar();
}
总结:
1.对象被移动后就不要在对其进行操作了;
2.自己定义的copy构造或赋值等操作会不会被编译,取决于你代码中有无使用相关操作。(这就是自己写的copy构造函数等中断点不会命中的原因)