移动赋值运算符在这个代码中是如何实现的,它的作用是什么?
#include <iostream>
using namespace std;
class BigMemoryPool { private: static const int POOL_SIZE = 4096; int* mPool;
public: BigMemoryPool() : mPool(new int[POOL_SIZE]{0}) { cout << "call default init" << endl; }
// 编译器会优化移动构造函数,正常情况可能不会被执行 // 可以添加编译选项 “-fno-elide-constructors” 关闭优化来观察效果 BigMemoryPool(BigMemoryPool && other) noexcept { mPool = other.mPool; other.mPool = nullptr; cout << "call move init" << endl; }
BigMemoryPool & operator=(BigMemoryPool && other) noexcept { if (this != &other) { this->mPool = other.mPool; other.mPool = nullptr; } cout << "call op move" << endl; return *this; } void showPoolAddr() { cout << "pool addr:" << &(mPool[0]) << endl; }
~BigMemoryPool() { cout << "call destructor" << endl; }};
BigMemoryPool makeBigMemoryPool() { BigMemoryPool x; // 调用默认构造函数 x.showPoolAddr(); return x; // 返回临时变量,属于右值}
int main() { BigMemoryPool a(makeBigMemoryPool()); a.showPoolAddr(); a = makeBigMemoryPool(); a.showPoolAddr(); return 0;}
// 输出内容call default initpool addr:0x152009600instance addr:0x16fdfeda0pool addr:0x152009600instance addr:0x16fdfeda0 // 编译器优化,这里a和x其实是同一个实例,因此不会触发移动构造call default initpool addr:0x15200e600 // 新的临时变量,堆内存重新分配instance addr:0x16fdfed88 // 临时变量对象地址call op move // 移动赋值call destructorpool addr:0x15200e600 // a的Pool指向的内存地址变成新临时对象分配的地址,完成转移instance addr:0x16fdfeda0 // a对象的地址没有变化call destructor
移动赋值运算符在代码中是这样实现的:BigMemoryPool & operator=(BigMemoryPool && other) noexcept。它的作用是接受一个BigMemoryPool类型的右值引用,并将该对象的资源“移动”到当前对象。在操作符的实现中,首先检查自赋值的情况,然后移动资源,并将原对象的资源指针设置为nullptr。这样,原对象在销毁时不会释放已经移动的资源,避免了资源泄漏。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。