经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++智能指针
来源:cnblogs  作者:Arthurian  时间:2023/9/18 9:04:22  对本文有异议

智能指针是C++语言中一种方便、安全的内存管理工具。智能指针可以自动管理对象的生命周期,避免手动分配和释放内存时可能出现的内存泄漏和悬挂指针等问题。在C++11标准中,引入了三种智能指针:unique_ptr、shared_ptr 和 weak_ptr。

类型 含义 备注
std::unique_ptr   独占资源所有权的指针。
std::shared_ptr   共享资源所有权的指针。
std::weak_ptr   享资源的观察者,需要和 std::shared_ptr 一起使用,不影响资源的生命周期。

unique_ptr 是一种独占式智能指针,它拥有对一个对象的唯一所有权,不能与其他智能指针共享对象所有权。当 unique_ptr 超出范围或被显式释放时,它所拥有的对象会被自动销毁。

shared_ptr 是一种共享式智能指针,它可以与其他 shared_ptr 共享一个对象。shared_ptr 使用引用计数技术来记录有多少个 shared_ptr 指向同一个对象,当引用计数为0时,对象会被自动销毁。

weak_ptr 是一种弱引用智能指针,它指向一个由 shared_ptr 管理的对象,但不会增加对象的引用计数。weak_ptr 用于解决循环引用问题,例如两个对象相互引用,导致它们的引用计数永远不会为0,从而无法自动销毁。

使用智能指针可以大大简化内存管理,减少内存泄漏和悬挂指针等问题。同时,智能指针还可以帮助程序员更好地编写多线程程序,避免竞态条件等问题。

下面是一个简单的示例程序,演示了如何使用 unique_ptr 和 shared_ptr:

 

  1. 1 #include <iostream>
  2. 2 #include <memory>
  3. 3
  4. 4 struct Foo {
  5. 5 Foo() { std::cout << "Foo::Foo\n"; }
  6. 6 ~Foo() { std::cout << "Foo::~Foo\n"; }
  7. 7 };
  8. 8
  9. 9 int main() {
  10. 10 std::unique_ptr<Foo> p1(new Foo); // 使用 unique_ptr 管理 Foo 对象的生命周期
  11. 11 {
  12. 12 std::shared_ptr<Foo> p2 = std::make_shared<Foo>(); // 使用 shared_ptr 管理 Foo 对象的生命周期
  13. 13 {
  14. 14 std::shared_ptr<Foo> p3 = p2; // p2 和 p3 共享 Foo 对象
  15. 15 } // p3 超出范围,引用计数减1
  16. 16 } // p2 超出范围,引用计数减1,Foo 对象被销毁
  17. 17 // p1 超出范围,Foo 对象被销毁
  18. 18 return 0;
  19. 19 }

在上面的示例程序中,我们创建了一个 Foo 对象,并使用 unique_ptr 和 shared_ptr 来管理它的生命周期。在 p2 和 p3 共享 Foo 对象时,它们的引用计数都为2。当 p3 超出范围时,引用计数减1;当 p2 超出范围时,引用计数再减1,Foo 对象被自动销毁。最后,当 p1 超出范围时,Foo 对象再次被销毁。

除了unique_ptr和shared_ptr,C++还有weak_ptr,它是一种不控制对象生命周期的智能指针。它指向一个由shared_ptr管理的对象,但不会增加对象的引用计数。它主要用于解决循环引用问题,例如两个对象相互引用,导致它们的引用计数永远不会为0,从而无法自动销毁。

下面是一个使用weak_ptr的示例程序:

  1. 1 #include <iostream>
  2. 2 #include <memory>
  3. 3
  4. 4 struct Foo {
  5. 5 void bar() { std::cout << "Foo::bar\n"; }
  6. 6 ~Foo() { std::cout << "Foo::~Foo\n"; }
  7. 7 };
  8. 8
  9. 9 int main() {
  10. 10 std::shared_ptr<Foo> p1(new Foo); // 使用 shared_ptr 管理 Foo 对象的生命周期
  11. 11 std::weak_ptr<Foo> wp1 = p1; // wp1 指向 p1 管理的 Foo 对象,但不增加引用计数
  12. 12 {
  13. 13 std::shared_ptr<Foo> p2 = wp1.lock(); // 使用 lock() 获取 shared_ptr
  14. 14 if (p2) {
  15. 15 p2->bar(); // 如果 p2 不为空,调用 bar() 函数
  16. 16 }
  17. 17 } // p2 超出范围,引用计数减1
  18. 18 // wp1 超出范围,因为引用计数已经为0,所以 Foo 对象被销毁
  19. 19 return 0;
  20. 20 }

在这个示例程序中,我们创建了一个 Foo 对象,使用 shared_ptr 和 weak_ptr 来管理它的生命周期。weak_ptr 用于解决循环引用问题,因此它不控制对象生命周期。当最后一个拥有该对象的 shared_ptr 不存在时,该对象被自动销毁。因此,在上面的示例程序中,当 p2 超出范围时,引用计数减1,Foo 对象将被销毁。当 wp1 超出范围时,因为引用计数已经为0,所以 Foo 对象再次被销毁。

另外,C++还提供了一种名为“std::enable_shared_from_this”的模板类,它允许智能指针在对象的成员函数中获取对对象的共享所有权。

下面是一个使用std::enable_shared_from_this的示例程序:

  1. 1 #include <iostream>
  2. 2 #include <memory>
  3. 3
  4. 4 struct Foo : std::enable_shared_from_this<Foo> {
  5. 5 void bar() {
  6. 6 std::cout << "Foo::bar\n";
  7. 7 auto sptr = shared_from_this();
  8. 8 if (sptr) {
  9. 9 sptr->baz();
  10. 10 }
  11. 11 }
  12. 12 void baz() {
  13. 13 std::cout << "Foo::baz\n";
  14. 14 }
  15. 15 };
  16. 16
  17. 17 int main() {
  18. 18 std::shared_ptr<Foo> p1(new Foo); // 使用 shared_ptr 管理 Foo 对象的生命周期
  19. 19 p1->bar(); // 在 bar() 中使用 enable_shared_from_this 获取对 Foo 对象的共享所有权,并调用 baz() 函数
  20. 20 // p1 超出范围,引用计数减1,因为 enable_shared_from_this 不增加引用计数
  21. 21 // Foo 对象被销毁
  22. 22 return 0;
  23. 23 }

在这个示例程序中,我们创建了一个 Foo 对象,使用 shared_ptr 管理它的生命周期,并在它的成员函数 bar() 中使用 enable_shared_from_this 获取对它的共享所有权。在 bar() 中,我们还调用了另一个成员函数 baz()。当 p1 超出范围时,引用计数减1,因为 enable_shared_from_this 不增加引用计数,所以 Foo 对象被销毁。当最后一个拥有该对象的 shared_ptr 不存在时,该对象被自动销毁。

另外,C++的智能指针还提供了一些功能,如“std::atomic_shared_ptr”和“std::shared_ptr_future”,可以让你在多线程环境中更安全地使用智能指针。这些功能可以帮助你避免多线程竞争条件等问题。

除此之外,C++还提供了一些更高级的模板库,如“Boost”和“Qt”,其中包含更多高级的智能指针和内存管理功能。例如,Boost库中的“boost::interprocess”库提供了跨进程内存管理和共享访问等功能。这些高级功能可以让你更加灵活地管理内存和开发大规模的应用程序。

总之,C++的智能指针是一个非常强大和灵活的内存管理工具。通过使用不同类型的智能指针和遵循RAII原则,你可以在C++程序中更安全、更有效地管理内存和其他资源。

原文链接:https://www.cnblogs.com/Arthurian/p/17407347.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号