来自新世界:智能指针

不会发生内存泄漏的东西

智能指针的三个模板:auto_ptr  unique_ptr shared_ptr

当智能指针过期时,其析构函数会自动调用delete来释放内存。

void remodel(std::string& str){
  std::auto_ptr<std::string> ps(new std::string(str));
  *ps = str;
  cout << *ps;
  return;
}

注意所有指针都有一个explicit的构造函数,因此不能这样做:

shared_ptr<double> pd;
double *p_reg = new double;
//pd = p_reg;   不允许,需要显示转换
pd = shared_ptr<double>(p_reg);

事实上,我们可以发现,在编译文件时,vs code会发出警告,那是因为C++11已经要抛弃这个auto_ptr了。

为啥呢?

这个是因为有一个东西叫所有权,当一个智能指针赋值给了另外一个时,原来的就会放弃它的所有权,因此再次用原来的智能指针访问数据时就会出错。(我们称为“悬挂指针”)

void remodel(std::string& str){
  std::auto_ptr<std::string> ps(new std::string(str));
  *ps = str;
  auto_ptr<string> pt = ps;
  cout << *pt;
  cout << *ps;   //这时系统会卡住
  return;  
}

怎么办?

可以把auto_ptr换成shared_ptr或者unique_ptr,前者的机制是当有多个指针指向同一对象时,引用计数增加,在析构时(先析构)那个最后声明的指针,其析构函数把计数器数减一,直到计数器降低到0时才会释放分配的空间。后者的机制是在使用等于号那一步编译器就报错了。但其实也不是不能通过等于号来给unique_ptr指针赋值,如果给它赋值的是临时右值,就不会报错,因为反正这个右值它很快就会被销毁了。

unique_ptr<string> demo(const char*s){
  unique_ptr<string> temp(new string(s));
  return temp;
}

unique_ptr<string> ps;
ps = demo("Uniquely special");   //编译器不会报错

事实上也可以单纯的用等号,右值也不用是临时变量,在要转移的指针上加个move方法就行

怎么选择智能指针

如果有多个指针指向同一个元素,比如有很多个对象,但是每个对象里面都有两个指针,指向某个最大值和最小值,这时就要用shared_ptr

发布者

我乃堂堂SCUT的一条咸鱼!

发表评论

电子邮件地址不会被公开。 必填项已用*标注