unique_ptr的移动语义是其核心特性,它允许你安全地将一个动态分配对象的所有权从一个
unique_ptr实例转移到另一个,而无需进行深度拷贝。这本质上意味着资源(比如堆上的对象)的所有权可以被“挪走”,原有的
unique_ptr随即变为空,确保始终只有一个
unique_ptr管理该资源,从而避免了双重释放等问题。
当我第一次接触
unique_ptr时,它给我最大的感受就是“安全感”。那种独占所有权的设计,配合RAII,简直是管理堆内存的福音。而这份安全感的核心,很大程度上就来源于它的移动语义。
想象一下,你有一个
unique_ptr<MyObject> ptr1(new MyObject());,现在你想把这个
MyObject的所有权交给另一个
unique_ptr,比如
ptr2。如果允许拷贝,那就会出现两个
unique_ptr指向同一个
MyObject,当它们各自析构时,就会尝试两次
delete,这绝对是灾难。
unique_ptr很聪明,它直接禁用了拷贝构造函数和拷贝赋值运算符。
但有时候,我们确实需要“传递”这个资源。比如,一个函数创建了一个对象,然后想把它返回给调用者;或者在一个容器里,我们想把一个
unique_ptr从一个位置移动到另一个位置。这时候,移动语义就派上用场了。

全面的AI聚合平台,一站式访问所有顶级AI模型


unique_ptr提供了移动构造函数和移动赋值运算符。当使用
std::move将一个
unique_ptr实例作为右值引用传递时,实际上发生的是所有权的转移:
- 源
unique_ptr
所持有的原始指针(指向MyObject
的地址)被“偷走”了。 - 目标
unique_ptr
获得了这个原始指针,现在它拥有了MyObject
。 - 源
unique_ptr
的原始指针被置为nullptr
,它不再管理任何资源。
这意味着,一旦移动完成,你不能再通过源
unique_ptr访问原来的
MyObject了,因为它已经“空”了。这完美地实现了独占所有权的概念:资源从A挪到了B,A就不再拥有它了。这种机制不仅安全,而且高效,因为它避免了昂贵的深拷贝操作,仅仅是几个指针的赋值和置空。
#include <iostream> #include <memory> #include <vector> #include <string> class MyResource { public: int id_; MyResource(int id) : id_(id) { std::cout << "MyResource " << id_ << " constructed." << std::endl; } ~MyResource() { std::cout << "MyResource " << id_ << " destructed." << std::endl; } void doSomething() { std::cout << "MyResource " << id_ << " doing something." << std::endl; } }; std::unique_ptr<MyResource> createResource(int id) { // 函数内部创建unique_ptr,并返回 // 这里会隐式地发生移动 return std::make_unique<MyResource>(id); } int main() { std::cout << "--- Initial unique_ptr ---" << std::endl; std::unique_ptr<MyResource> ptr1 = std::make_unique<MyResource>(101); if (ptr1) { ptr1->doSomething(); } std::cout << "\n--- Moving ownership ---" << std::endl; std::unique_ptr<MyResource> ptr2 = std::move(ptr1); // 显式移动 if (ptr1) { // ptr1 现在是空的 std::cout << "ptr1 still holds resource!" << std::endl; } else { std::cout << "ptr1 is now null." << std::endl; } if (ptr2) { ptr2->doSomething(); // ptr2 现在拥有资源 } std::cout << "\n--- Moving from function return ---" << std::endl; std::unique_ptr<MyResource> ptr3 = createResource(202); // 隐式移动 if (ptr3) { ptr3->doSomething(); } std::cout << "\n--- Moving into a vector ---" << std::endl; std::vector<std::unique_ptr<MyResource>> resources; resources.push_back(std::move(ptr2)); // 将ptr2持有的资源移动到vector中 // ptr2 再次变为空 if (ptr2) { std::cout << "ptr2 still holds resource after push_back!" << std::endl; } else { std::cout << "ptr2 is now null after push_back." << std::endl; } resources.push_back(std::move(ptr3)); // 将ptr3持有的资源移动到vector中 // ptr3 再次变为空 if (ptr3) { std::cout << "ptr3 still holds resource after push_back!" << std::endl; } else { std::cout << "ptr3 is now null after push_back." << std::endl; } std::cout << "\n--- Accessing resources in vector ---" << std
以上就是C++unique_ptr移动语义与转移所有权的详细内容,更多请关注知识资源分享宝库其它相关文章!
相关标签: access ai c++ ios 运算符 赋值运算符 构造函数 指针 堆 引用传递 delete 对象 大家都在看: C++如何检查文件存在 access函数替代方案 C++井字棋AI实现 简单决策算法编写 如何为C++搭建边缘AI训练环境 TensorFlow分布式训练配置 怎样用C++开发井字棋AI 简单决策算法实现方案 怎样为C++配置嵌入式AI开发环境 TensorFlow Lite Micro移植指南
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。