返回

智能指针:安全简洁的动态内存管理 利器

后端


内存管理对于 C++程序员来说一直是一个颇具难度的课题。我们很容易因为内存泄漏或内存超限造成很多程序的运行错误,进而造成灾难性的后果。智能指针的引入将有效降低内存管理方面的错误概率,进而提高程序的健壮性。


说起智能指针,就不得不提动态内存分配,所谓动态内存分配,就是由运行时的环境,一般为操作系统,向进程或线程分配内存。智能指针就像指引我们迷津中的明灯,时时刻刻的告诉我们去指向哪里,去取什么数据,并根据我们需求的资源和指向的位置自动增大或者减少我们申请内存的大小。


智能指针也并非万无一逸的,我们也可能因为对智能指针使用的错误而导致我们的程序出现一些莫名其妙的错误。


我们主要对以下四个智能指针进行简单的了解:


1.auto_ptr


auto_ptr是一种已经被废弃的智能指针,也是我们使用最为简单和很容易上手的智能指针。


// 声明自有智能指针m_ptr
auto_ptr<int> m_ptr;

auto_ptr的句法主要有:


  • auto_ptr:用于声明自有指针。
  • auto_ptr:为某个对象的自动指针建立一个自动指针类。

注意:


  • auto_ptr被废弃的主要原因是它不支持所有权的转让,也就是说一个对象不能被多个auto_ptr所引用,一旦引用则所有权转让。
  • auto_ptr是不能被拷贝或赋值的,但我们可以通过move(或 std::move()) 函数来进行转让。

2.unique_ptr


unique_ptr是一种所有权转让方式的智能指针,即任何时刻它只被一个unique_ptr拥有,如果我们想对所有权转让,只能通过move(或 std::move())函数。


unique_ptr的句法主要有:


  • unique_ptr: 声明一个独一无二的指针。
  • unique_ptr: 对于被自动指针引用 的对象而建立一个unique_ptr类。
  • up_up(unique_ptr): 用于多个unique_ptr相互之间所有权转让。
  • up_move(unique_ptr): 用于unique_ptr与其他指针类型之间所有权转让。

关于为何unique_ptr能够对接管对象具有唯一权,主要有以下几个特性:


  • unique_ptr可以对接管对象的所有权进行转让。
  • unique_ptr不支持拷贝和赋值,也就是说unique_ptr的语义是“所有或无”的语义,而不存在“一份多用”的语义。

2.1测试用例


创建 unique_ptr 对象

unique_ptr<Person>ptr1(new Person("John"));
Person*ptr1_= ptr1.get();

向上赋值(error)

Person *ptr2 = ptr1;//error 无法隐式赋值

释放接管对象的所有权

ptr1.release();

重新请求接管对象的所有权

Person* personPtr= ptr1.release();

所有权转让(error)

unique_ptr<Person>ptr2=ptr1;//error无法进行转让

3.shared_ptr


shared_ptr是一种拥有共享所有权的智能指针。这种智能指针主要用在多个对象共享内存的时候,对象的内存由多个指针所引用,并由智能指针管理对象的内存,引用计数也是由这个智能指针来进行记录的。


shared_ptr 的句法主要有:


  • shared_ptr: 用于声明共享指针。
  • shared_ptr: 用于被自动指针引用 的对象建立一个shared_ptr类。

我们通过reset()方法来对智能指针进行重置:

shared_ptr<string> sp_str(new string());
sp_str.reset(newstring("zhangsi"))
cout<<*sp_str<<endl;

通过输出,我们可以看到shared_ptr进行重置后会对旧的所有权释放,并且将新的所有权接管。


shared_ptr通过weak_ptr来实现对象的软引用,我们通过weak_ptr来对sp_str所指向的智能指针进行监视,我们可以通过判断weak_ptr是否非空来实现判断我们所指向的智能指针是否被销毁。
弱指针的句法如下:

int*ptr=&x;
weak_ptr<int>wptr=weak_ptr<int>(ptr);

4.weak_ptr


weak_ptr是weak pointer的缩写,意即弱指针,是一种通过关联智能指针释放后,我们依旧通过它来检索到被销毁智能指针所指向的内存块,从而实现对销毁内存的继续读写。weak_ptr的句法主要有:


  • weak_ptr:用于声明一个weak_ptr智能指针。
  • weak_ptr:为某一对象建立一个 weak_ptr类。
  • lock(weak_ptr): 检查智能指针是否已经销毁,如果销毁,则返回 空指针。

weak_ptr和shared_ptr一样,可以通过reset()来实现重置:


weak_ptr<string> wp_str(newstring("Zhang"));
wp_str.lock()->assign("wangwu");
cout<<*wp_str.lock()->assign("wangwu")<<endl;

也可以通过lock函数来对weak_ptr进行测试,测试智能指针是否已经销毁

shared_ptr<string> sp_str(newstring("zhangsi"));
wp_str=wp_str.lock();
if(wp_str) cout<<"对象仍然存在!";

最后,希望我们可以通过这篇文章对智能指针的各种性质和使用方法进行深刻的了解,并且能够在今后的项目中熟练的应用他们来对我们的内存进行更为有效的管理。