【C++编程】智能指针shared_ptr与unique_ptr

智能指针shared_ptr与unique_ptr

unique_ptr支持动态数组,而shared_ptr不能直接支持动态数组:

std::unique_ptr<int []> ptr(new int[10]);   //合法,
std::shared_ptr<int []> ptr(new int[10]); //是不合法的

如果通过std::shared_ptr来构造动态数组,则需要显式指定删除器,比如下面的代码: 

std::shared_ptr<int> p(new int[10], [](int* p){delete[] p;}); //指定delete[]

unique_ptr指定删除器的方法和std:: shared_ptr是有区别的:

std:: shared_ptr<int> ptr(new int(1), [](int*p){delete p;}); //正确
std::unique_ptr<int> ptr(new int(1), [](int*p){delete p;}); //错误

std::unique_ptr指定删除器的时候需要确定删除器的类型,所以不能直接像shared_ptr指定删除器,正确写法如下:

std::unique_ptr<int, void(*)(int*)> ptr(new int(1), [](int*p){delete p;});

上面这种写法在lambda没有捕获变量的情况下是正确的,如果捕获了变量则会编译报错:

std::unique_ptr<int, void(*)(int*)> ptr(new int(1), [&](int*p){delete p;}); //错误,因为捕获了变量

为什么lambda捕获了变量作为unique_ptr就会报错呢,因为lambda在没有捕获变量的情况下是可以直接转换为函数指针的,捕获了就不能转换为函数指针。如果希望unique_ptr的删除器支持lambda,可以这样写:

std::unique_ptr<int, std::function<void(int*)>> ptr(new int(1), [&](int*p){delete p;});

1. 使用lambda表达式

#include <iostream>
#include <memory>

int main()
{
  std::shared_ptr<int>(new int[5](), [](int *x) {
    std::cout << "Delete function called" << std::endl;
    delete[] x;
  });
}

 

 2. 使用普通函数

#include <iostream>
#include <memory>

void deleter(int *x) {
  std::cout << "Delete function called" << std::endl;
  delete[] x;
}

int main() {
  std::shared_ptr<int>(new int[5](), deleter);
}

 

3.使用类重载:

#include <iostream>
#include <memory>

class Deleter {
public:
  void operator()(int *x) {
    std::cout << "Delete function called" << std::endl;
    delete[] x;
  }
};

int main() {
  std::shared_ptr<int>(new int[5](), Deleter());
}

 

 4. 使用std::default_delete:

#include <memory>
#include <vector>
#include <algorithm>

int main() {
  {
    std::shared_ptr<int> shared_good(new int[10], std::default_delete<int[]>());
  }

  std::vector<int *> v;
  for (int n = 0; n < 100; ++n)
    v.push_back(new int(n));
  std::for_each(v.begin(), v.end(), std::default_delete<int>());
}

 

#include <iostream>
#include <memory>

struct Foo {
   Foo() { std::cout << "Foo...\n"; }
   ~Foo() { std::cout << "~Foo...\n"; }
};

struct D {
   void operator()(Foo *p) {
     std::cout << "Calling delete for Foo object... \n";
     delete p;
   }
};

int main() {
  std::cout << "Creating new Foo...\n";

  //up owns the Foo pointer (deleter D)
  std::unique_ptr<Foo, D> up(new Foo(), D());

  std::cout << "Replace owned Foo with a new Foo...\n";
  up.reset(new Foo()); // calls deleter for the old one

  std::cout << "Release and delete the owned Foo...\n";
  up.reset(nullptr);
}

输出:

Creating new Foo...
Foo...
Replace owned Foo with a new Foo...
Foo...
Calling delete for Foo object... 
~Foo...
Release and delete the owned Foo...
Calling delete for Foo object... 
~Foo...

参考资料

1. c++11:std::default_delete

2. 智能指针详解

posted @ 2021-09-07 21:48  苏格拉底的落泪  阅读(182)  评论(0编辑  收藏  举报