智能指针shared_ptr 的 reset使用

shared_ptr 的 reset() 有 4 个重载版本,如下:

 
  1. void reset() noexcept; (1) (since C++11)

  2. template< class Y >

  3. void reset( Y* ptr ); (2) (since C++11)

  4. template< class Y, class Deleter >

  5. void reset( Y* ptr, Deleter d ); (3) (since C++11)

  6. template< class Y, class Deleter, class Alloc >

  7. void reset( Y* ptr, Deleter d, Alloc alloc ); (4) (since C++11)

常用到的应该是前 3 个版本,这里不举例第 4 个版本,因为我也没用过^_^ 

1,void reset() 版本

这个函数是最简单的,其作用:释放托管对象的所有权(如果有),调用后,该智能指针不再管理任何对象。注意,这里的释放并不是真正地去释放,只是引用计数减 1,而释放是引用计数为 0 时自行进行的。

 
  1. #include <memory>

  2. #include <iostream>

  3. struct Foo {

  4. Foo(int n = 0) noexcept : bar(n) {

  5. std::cout << "Foo::Foo(), bar = " << bar << " @ " << this << '\n';

  6. }

  7. ~Foo() {

  8. std::cout << "Foo::~Foo(), bar = " << bar << " @ " << this << "\n";

  9. }

  10. int getBar() const noexcept { return bar; }

  11. private:

  12. int bar;

  13. };

  14. void deleter(Foo *f)

  15. {

  16. delete []f;

  17. }

  18. int main()

  19. {

  20. std::cout << "1) unique ownership\n";

  21. {

  22. std::shared_ptr<Foo> sptr = std::make_shared<Foo>(100);

  23. std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = "

  24. << sptr.use_count() << '\n';

  25. // Reset the shared_ptr without handing it a fresh instance of Foo.

  26. // The old instance will be destroyed after this call.

  27. std::cout << "call sptr.reset()...\n";

  28. sptr.reset(); // calls Foo's destructor here

  29. std::cout << "After reset(): use_count() = " << sptr.use_count()

  30. << ", sptr = " << sptr << '\n';

  31. } // No call to Foo's destructor, it was done earlier in reset().

  32. return 0;

  33. }

可以看到在调用 reset() 后,调用了对象的析构函数进行释放。我们看 reset() 的另一种情况:

 
  1. #include <memory>

  2. #include <iostream>

  3. struct Foo {

  4. Foo(int n = 0) noexcept : bar(n) {

  5. std::cout << "Foo::Foo(), bar = " << bar << " @ " << this << '\n';

  6. }

  7. ~Foo() {

  8. std::cout << "Foo::~Foo(), bar = " << bar << " @ " << this << "\n";

  9. }

  10. int getBar() const noexcept { return bar; }

  11. private:

  12. int bar;

  13. };

  14. int main()

  15. {

  16. std::cout << "1) unique ownership\n";

  17. {

  18. std::shared_ptr<Foo> sptr = std::make_shared<Foo>(100);

  19. std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = "

  20. << sptr.use_count() << '\n';

  21. // Reset the shared_ptr without handing it a fresh instance of Foo.

  22. // The old instance will be destroyed after this call.

  23. std::cout << "call sptr.reset()...\n";

  24. sptr.reset(); // calls Foo's destructor here

  25. std::cout << "After reset(): use_count() = " << sptr.use_count()

  26. << ", sptr = " << sptr << '\n';

  27. } // No call to Foo's destructor, it was done earlier in reset().

  28. std::cout << "1) unique ownership\n";

  29. {

  30. std::shared_ptr<Foo> sptr = std::make_shared<Foo>(100);

  31. std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = "

  32. << sptr.use_count() << '\n';

  33. std::shared_ptr<Foo> sptr1 = sptr;

  34. // Reset the shared_ptr without handing it a fresh instance of Foo.

  35. // The old instance will be destroyed after this call.

  36. std::cout << "call sptr1.reset()...\n";

  37. sptr1.reset(); // not calls Foo's destructor here

  38. std::cout << "After reset(): use_count() = " << sptr.use_count()

  39. << ", sptr = " << sptr << '\n';

  40. } // No call to Foo's destructor, it was done earlier in reset().

  41. return 0;

  42. }

可以看到 Foo::bar = 100, use_count() = 2,此时两个智能指针都管理着 0x1029028 的资源,当调用 sptr1.reset(); 后,这个资源就少了一个管理者,所以 After reset(): use_count() = 1, sptr = 0x1029028,当离开作用域后,此资源才被释放。

2,模板版本带一个参数

template< class Y >
void reset( Y* ptr );  用ptr指向的对象替换托管对象

 
  1. #include <memory>

  2. #include <iostream>

  3. struct Foo {

  4. Foo(int n = 0) noexcept : bar(n) {

  5. std::cout << "Foo::Foo(), bar = " << bar << " @ " << this << '\n';

  6. }

  7. ~Foo() {

  8. std::cout << "Foo::~Foo(), bar = " << bar << " @ " << this << "\n";

  9. }

  10. int getBar() const noexcept { return bar; }

  11. private:

  12. int bar;

  13. };

  14. int main()

  15. {

  16. std::cout << "\n1) unique ownership\n";

  17. {

  18. std::shared_ptr<Foo> sptr = std::make_shared<Foo>(200);

  19. std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = "

  20. << sptr.use_count() << '\n';

  21. // Reset the shared_ptr, hand it a fresh instance of Foo.

  22. // The old instance will be destroyed after this call.

  23. std::cout << "call sptr.reset()...\n";

  24. sptr.reset(new Foo{222});

  25. std::cout << "After reset(): use_count() = " << sptr.use_count()

  26. << ", sptr = " << sptr << "\nLeaving the scope...\n";

  27. } // Calls Foo's destructor.

  28. return 0;

  29. }

可以看到在  sptr.reset(new Foo{222}); 后,释放了 0x17d1028 指向的资源,当前指向的资源为 0x17d1040,离开作用域后自动释放。

3, 模板版本还两个参数

template<class Y, class Deleter>

void reset(Y *ptr, Deleter d)

带删除器的版本只会用在数组对象释放的情况,如果是数组对象的情况下不用删除器,则行为是未定义的。如:

 
  1. #include <memory>

  2. #include <iostream>

  3. struct Foo {

  4. Foo(int n = 0) noexcept : bar(n) {

  5. std::cout << "Foo::Foo(), bar = " << bar << " @ " << this << '\n';

  6. }

  7. ~Foo() {

  8. std::cout << "Foo::~Foo(), bar = " << bar << " @ " << this << "\n";

  9. }

  10. int getBar() const noexcept { return bar; }

  11. private:

  12. int bar;

  13. };

  14. int main()

  15. {

  16. std::cout << "1) unique ownership\n";

  17. {

  18. std::shared_ptr<Foo> sptr = std::make_shared<Foo>(100);

  19. std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = "

  20. << sptr.use_count() << '\n';

  21. // Reset the shared_ptr without handing it a fresh instance of Foo.

  22. // The old instance will be destroyed after this call.

  23. std::cout << "call sptr.reset()...\n";

  24. sptr.reset(new Foo[3]); // calls Foo's destructor here

  25. std::cout << "After reset(): use_count() = " << sptr.use_count()

  26. << ", sptr = " << sptr << '\n';

  27. } // No call to Foo's destructor, it was done earlier in reset().

  28. return 0;

  29. }

正确用法可以是这样:

 
  1. #include <memory>

  2. #include <iostream>

  3. struct Foo {

  4. Foo(int n = 0) noexcept : bar(n) {

  5. std::cout << "Foo::Foo(), bar = " << bar << " @ " << this << '\n';

  6. }

  7. ~Foo() {

  8. std::cout << "Foo::~Foo(), bar = " << bar << " @ " << this << "\n";

  9. }

  10. int getBar() const noexcept { return bar; }

  11. private:

  12. int bar;

  13. };

  14. void customDeleter(Foo *f)

  15. {

  16. if(f)

  17. {

  18. delete []f;

  19. }

  20. }

  21. int main()

  22. {

  23. std::cout << "1) unique ownership\n";

  24. {

  25. std::shared_ptr<Foo> sptr = std::make_shared<Foo>(100);

  26. std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = "

  27. << sptr.use_count() << '\n';

  28. // Reset the shared_ptr without handing it a fresh instance of Foo.

  29. // The old instance will be destroyed after this call.

  30. std::cout << "call sptr.reset()...\n";

  31. sptr.reset(new Foo[3], customDeleter); // calls Foo's destructor here

  32. std::cout << "After reset(): use_count() = " << sptr.use_count()

  33. << ", sptr = " << sptr << '\n';

  34. } // No call to Foo's destructor, it was done earlier in reset().

  35. return 0;

  36. }

 添加删除函数:

 
  1. void customDeleter(Foo *f)

  2. {

  3. if(f)

  4. {

  5. delete []f;

  6. }

  7. }

reset 调用时指定删除器: sptr.reset(new Foo[3], customDeleter);

因为只有释放数组对象时才需要指定删除器,所以实现就是 delete [],我们看结果:

最后调用的 3 个析构函数。

还可以使用 std::default_delete 模板,如:sptr.reset(new Foo[3], std::default_delete<Foo[]>());

 
  1. #include <memory>

  2. #include <iostream>

  3. struct Foo {

  4. Foo(int n = 0) noexcept : bar(n) {

  5. std::cout << "Foo::Foo(), bar = " << bar << " @ " << this << '\n';

  6. }

  7. ~Foo() {

  8. std::cout << "Foo::~Foo(), bar = " << bar << " @ " << this << "\n";

  9. }

  10. int getBar() const noexcept { return bar; }

  11. private:

  12. int bar;

  13. };

  14. int main()

  15. {

  16. std::cout << "1) unique ownership\n";

  17. {

  18. std::shared_ptr<Foo> sptr = std::make_shared<Foo>(100);

  19. std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = "

  20. << sptr.use_count() << '\n';

  21. // Reset the shared_ptr without handing it a fresh instance of Foo.

  22. // The old instance will be destroyed after this call.

  23. std::cout << "call sptr.reset()...\n";

  24. sptr.reset(new Foo[3], std::default_delete<Foo[]>());

  25. std::cout << "After reset(): use_count() = " << sptr.use_count()

  26. << ", sptr = " << sptr << '\n';

  27. } // No call to Foo's destructor, it was done earlier in reset().

  28. return 0;

  29. }

 

同样释放正常。

智能指针shared_ptr 的 reset使用_智能指针reset-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值