现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

智能指针c++++中自动管理内存的工具,主要包括unique_ptr、shared_ptr和weak_ptr。1. unique_ptr用于独占所有权,不可复制,转移需用std::move,销毁时自动删除对象;2. shared_ptr允许多个指针共享同一对象,通过引用计数管理生命周期,但需注意循环引用问题;3. weak_ptr作为弱引用不增加引用计数,用于解决循环引用及实现缓存等场景。合理选择智能指针可避免内存泄漏并提升效率。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

智能指针,说白了,就是帮你自动管理内存的指针。现代 c++ 里,它们已经是标配了,unique_ptr、shared_ptr 和 weak_ptr,各有各的用处和侧重点,用错了地方,轻则效率打折,重则内存泄漏。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

unique_ptr、shared_ptr、weak_ptr 就像是内存管理战场上的三员大将,各有千秋,用对了地方才能发挥最大威力。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

解决方案

首先,unique_ptr,顾名思义,它所指向的对象只能被一个 unique_ptr 拥有。这意味着,所有权是独占的,不能简单地复制。当 unique_ptr 销毁时,它所指向的对象也会被自动删除。这避免了忘记 delete 造成的内存泄漏。

立即学习C++免费学习笔记(深入)”;

#include <iostream> #include <memory>  class MyClass { public:     MyClass(int value) : value_(value) {         std::cout << "MyClass constructed with value: " << value_ << std::endl;     }     ~MyClass() {         std::cout << "MyClass destructed with value: " << value_ << std::endl;     }      int getValue() const { return value_; }  private:     int value_; };   int main() {     // 创建一个 unique_ptr,指向一个 MyClass 对象     std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>(10);     std::cout << "Value: " << ptr1->getValue() << std::endl;      // 尝试复制 unique_ptr 会导致编译错误     // std::unique_ptr<MyClass> ptr2 = ptr1; // 错误:unique_ptr 不可复制      // 可以使用 std::move 转移所有权     std::unique_ptr<MyClass> ptr2 = std::move(ptr1);     std::cout << "Value: " << ptr2->getValue() << std::endl;      // 现在 ptr1 不再拥有对象,访问它会导致未定义行为     // std::cout << "Value: " << ptr1->getValue() << std::endl; // 避免这样做      // ptr2 在 main 函数结束时会被销毁,MyClass 对象也会被销毁     return 0; }

shared_ptr 则允许多个指针指向同一个对象,它使用引用计数来跟踪有多少个 shared_ptr 指向该对象。只有当引用计数降为零时,对象才会被删除。这使得在多个对象之间共享所有权变得非常方便。但是,循环引用会导致内存泄漏,需要小心。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

#include <iostream> #include <memory>  class MyClass { public:     MyClass(int value) : value_(value) {         std::cout << "MyClass constructed with value: " << value_ << std::endl;     }     ~MyClass() {         std::cout << "MyClass destructed with value: " << value_ << std::endl;     }      int getValue() const { return value_; }  private:     int value_; };  int main() {     // 创建一个 shared_ptr,指向一个 MyClass 对象     std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>(20);     std::cout << "Value: " << ptr1->getValue() << std::endl;     std::cout << "Reference count: " << ptr1.use_count() << std::endl;      // 复制 shared_ptr,引用计数增加     std::shared_ptr<MyClass> ptr2 = ptr1;     std::cout << "Value: " << ptr2->getValue() << std::endl;     std::cout << "Reference count: " << ptr1.use_count() << std::endl;     std::cout << "Reference count: " << ptr2.use_count() << std::endl;      // ptr1 和 ptr2 都指向同一个对象,该对象在 main 函数结束时会被销毁一次     return 0; }

最后,weak_ptr 是一种“弱引用”,它指向由 shared_ptr 管理的对象,但不增加引用计数。weak_ptr 可以用来观察对象是否仍然存在,而不会阻止对象被删除。这对于解决循环引用问题非常有用。

#include <iostream> #include <memory>  class MyClass { public:     MyClass(int value) : value_(value) {         std::cout << "MyClass constructed with value: " << value_ << std::endl;     }     ~MyClass() {         std::cout << "MyClass destructed with value: " << value_ << std::endl;     }      int getValue() const { return value_; }  private:     int value_; };  int main() {     // 创建一个 shared_ptr,指向一个 MyClass 对象     std::shared_ptr<MyClass> sharedPtr = std::make_shared<MyClass>(30);     std::cout << "Shared pointer value: " << sharedPtr->getValue() << std::endl;     std::cout << "Shared pointer reference count: " << sharedPtr.use_count() << std::endl;      // 创建一个 weak_ptr,指向同一个 MyClass 对象     std::weak_ptr<MyClass> weakPtr = sharedPtr;     std::cout << "Weak pointer expired: " << weakPtr.expired() << std::endl;      // 可以使用 weak_ptr 的 lock() 方法获取一个 shared_ptr     std::shared_ptr<MyClass> lockedPtr = weakPtr.lock();     if (lockedPtr) {         std::cout << "Locked pointer value: " << lockedPtr->getValue() << std::endl;         std::cout << "Shared pointer reference count: " << sharedPtr.use_count() << std::endl;     } else {         std::cout << "Weak pointer is expired." << std::endl;     }      // 释放 shared_ptr     sharedPtr.reset();     std::cout << "Shared pointer reference count: " << sharedPtr.use_count() << std::endl;     std::cout << "Weak pointer expired: " << weakPtr.expired() << std::endl;      // 再次尝试使用 weak_ptr 的 lock() 方法     lockedPtr = weakPtr.lock();     if (lockedPtr) {         std::cout << "Locked pointer value: " << lockedPtr->getValue() << std::endl;     } else {         std::cout << "Weak pointer is expired." << std::endl;     }      return 0; }

何时使用 unique_ptr?

当你希望对象的所有权是唯一的,并且在 unique_ptr 销毁时自动删除对象时,使用 unique_ptr。例如,在工厂函数中返回新创建的对象,或者在类中拥有一个独占的资源。

shared_ptr 如何避免循环引用导致的内存泄漏?

循环引用是指两个或多个对象互相持有 shared_ptr,导致引用计数永远不为零,对象永远无法被删除。解决循环引用的方法是使用 weak_ptr。一个对象持有另一个对象的 weak_ptr,而不是 shared_ptr,这样就不会增加引用计数。当需要访问对象时,可以使用 weak_ptr::lock() 方法获取一个 shared_ptr,如果对象已经被删除,lock() 方法会返回 nullptr。

weak_ptr 的使用场景有哪些?

除了解决循环引用问题,weak_ptr 还可以用于缓存。例如,一个缓存对象可以使用 weak_ptr 来持有缓存项,当缓存项不再被其他对象使用时,缓存对象会自动释放缓存项。还可以用于观察者模式,观察者可以使用 weak_ptr 来持有被观察者的引用,当被观察者被删除时,观察者可以自动取消订阅。

以上就是现代C++中的智能指针有哪些

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享