unique_ptr 概述:
- c++ 11模板库的<memory>头文件中定义的智能指针,即 unique_ptr 模板,用于自动释放 new 动态分布的内存空间。
- 只要将 new 运算符返回的指针 ptr 交给一个 unique_ptr 对象托管,就不必写 delete ptr 语句,托管 ptr 指针的 unique_ptr 对象在消亡时会自动执行 delete ptr。
- unique_ptr 对象能像指针 ptr 一样使用, *unique_ptr 就是 *ptr。
shared_ptr 与 unique_ptr 与有以上共同的特性,两者的区别在于:
- unique_ptr 不可以进行拷贝和赋值操作,每个unique_ptr对象都是原始指针的唯一所有者。
- shared_ptr 可以进行拷贝和赋值操作,每个 shared_ptr 都会记录它所指向对象的个数,一般称之为引用计数。当进行拷贝操作时他们所指向的对象的引用计数都会增加,一旦一个shared_ptr的引用计数变为0,它就会自动释放自己所管理的对象。
示例:
class Test { public: int value = 666; explicit Test() { std::cout << "Test();" << std::endl; } virtual ~Test() { std::cout << "virtrual ~Test();" << std::endl; } }; // unique_ptr 禁用了拷贝构造函数和赋值操作函数, 每个unique_ptr对象都是原始指针的唯一所有者 // unique_ptr(const unique_ptr&) = delete; // unique_ptr& operator=(const unique_ptr&) = delete; int main() { Test* test = new Test(); std::unique_ptr<Test> ptr1(test); ptr1 = std::make_unique<Test>(); // 推荐使用 make_unique 创建对象,而非 new // std::unique_ptr<Test> ptr4(test); 会产生运行时错误,程序结束时会重复释放导致段错误 // std::unique_ptr<Test> ptr4 = ptr1; 编译错误,禁用了赋值操作函数 // std::unique_ptr<Test> ptr4(ptr1); 编译错误,禁用了拷贝构造函数 ptr1.reset(new Test()); // 先调用析构函数删除旧对象,再调用构造函数生成新对象 std::unique_ptr<Test> ptr2 = std::move(ptr1); // 将 ptr1 指向内存指针的所有权交给 ptr2 , ptr1 置为 nullptr Test* ptr3 = ptr2.get(); // get() 获取 ptr2 指向 Test 的内存指针 std::cout << ptr3->value << std::endl; Test* last = ptr2.release(); // 释放 ptr2 对指针的所有权,ptr2置空,返回内存指针,需要 delete 手动释放内存空间 if (ptr2 == nullptr) { std::cout << "ptr2 is nullptr" << std::endl; } std::cout << last->value << std::endl; delete last; // 当智能指针 unique_ptr 拥有内存指针的所有权时,程序退出会自动调用析构函数释放内存空间 return 0; } // 输出如下: // Test(); // Test(); // virtrual ~Test(); // Test(); // virtrual ~Test(); // 666 // ptr2 is nullptr // 666 // virtrual ~Test();