- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
智能指针是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 #include <iostream> 2 #include <memory> 3 4 struct Foo { 5 Foo() { std::cout << " Foo::Foo\n " ; } 6 ~Foo() { std::cout << " Foo::~Foo\n " ; } 7 }; 8 9 int main() { 10 std::unique_ptr<Foo> p1( new Foo); // 使用 unique_ptr 管理 Foo 对象的生命周期 11 { 12 std::shared_ptr<Foo> p2 = std::make_shared<Foo>(); // 使用 shared_ptr 管理 Foo 对象的生命周期 13 { 14 std::shared_ptr<Foo> p3 = p2; // p2 和 p3 共享 Foo 对象 15 } // p3 超出范围,引用计数减1 16 } // p2 超出范围,引用计数减1,Foo 对象被销毁 17 // p1 超出范围,Foo 对象被销毁 18 return 0 ; 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 #include <iostream> 2 #include <memory> 3 4 struct Foo { 5 void bar() { std::cout << " Foo::bar\n " ; } 6 ~Foo() { std::cout << " Foo::~Foo\n " ; } 7 }; 8 9 int main() { 10 std::shared_ptr<Foo> p1( new Foo); // 使用 shared_ptr 管理 Foo 对象的生命周期 11 std::weak_ptr<Foo> wp1 = p1; // wp1 指向 p1 管理的 Foo 对象,但不增加引用计数 12 { 13 std::shared_ptr<Foo> p2 = wp1. lock (); // 使用 lock() 获取 shared_ptr 14 if (p2) { 15 p2->bar(); // 如果 p2 不为空,调用 bar() 函数 16 } 17 } // p2 超出范围,引用计数减1 18 // wp1 超出范围,因为引用计数已经为0,所以 Foo 对象被销毁 19 return 0 ; 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 #include <iostream> 2 #include <memory> 3 4 struct Foo : std::enable_shared_from_this<Foo> { 5 void bar() { 6 std::cout << " Foo::bar\n " ; 7 auto sptr = shared_from_this(); 8 if (sptr) { 9 sptr-> baz(); 10 } 11 } 12 void baz() { 13 std::cout << " Foo::baz\n " ; 14 } 15 }; 16 17 int main() { 18 std::shared_ptr<Foo> p1( new Foo); // 使用 shared_ptr 管理 Foo 对象的生命周期 19 p1->bar(); // 在 bar() 中使用 enable_shared_from_this 获取对 Foo 对象的共享所有权,并调用 baz() 函数 20 // p1 超出范围,引用计数减1,因为 enable_shared_from_this 不增加引用计数 21 // Foo 对象被销毁 22 return 0 ; 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++程序中更安全、更有效地管理内存和其他资源.
最后此篇关于C++智能指针的文章就讲到这里了,如果你想了解更多关于C++智能指针的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我在64位linux下使用c++,编译器(g++)也是64位的。当我打印某个变量的地址时,例如一个整数,它应该打印一个 64 位整数,但实际上它打印了一个 48 位整数。 int i; cout <<
我是一名优秀的程序员,十分优秀!