自动u ptr、唯一u ptr、共享u ptr和弱u ptr

先决条件—— 智能指针 C++库提供以下类型的智能指针的实现:

null
  • 自动_ptr
  • 独特的
  • 共享ptr
  • 弱ptr

它们都在内存头文件中声明。

自动_ptr

从C++11开始,该类模板已被弃用。 独特的 是一个具有类似功能的新设施,但安全性有所提高。 auto_ptr是一个智能指针,它管理通过新表达式获得的对象,并在auto_ptr本身被销毁时删除该对象。 当使用auto_ptr类描述一个对象时,它会存储一个指向单个分配对象的指针,以确保当它超出范围时,它指向的对象必须自动销毁。它是基于 排他性所有权模式 i、 e.同一类型的两个指针不能同时指向同一资源。如下面的程序所示,复制或分配指针会改变所有权,即源指针必须赋予目标指针所有权。

Auto pointer in C++

// C++ program to illustrate the use of auto_ptr
#include <iostream>
#include <memory>
using namespace std;
class A {
public :
void show() { cout << "A::show()" << endl; }
};
int main()
{
// p1 is an auto_ptr of type A
auto_ptr<A> p1( new A);
p1->show();
// returns the memory address of p1
cout << p1.get() << endl;
// copy constructor called, this makes p1 empty.
auto_ptr<A> p2(p1);
p2->show();
// p1 is empty now
cout << p1.get() << endl;
// p1 gets copied in p2
cout << p2.get() << endl;
return 0;
}


输出:

A::show()
0x1b42c20
A::show()
0          
0x1b42c20

auto_ptr的复制构造函数和赋值运算符实际上并不复制存储的指针,而是将其传输,使第一个auto_ptr对象为空。这是实现严格所有权的一种方法,这样在任何给定时间只有一个auto_ptr对象可以拥有指针,即在需要复制语义的地方不应使用auto_ptr。

为什么不推荐使用auto_ptr? 它以一种方式获取指针的所有权,即两个指针不应包含同一个对象。分配会转移所有权,并将右值自动指针重置为空指针。因此,由于上述无法复制的原因,它们不能在STL容器中使用。

独特的

std::unique_ptr是在C++11中开发的,作为std::auto_ptr的替代品。 unique_ptr是一种具有类似功能的新功能,但具有改进的安全性(无假拷贝分配)、添加的功能(删除器)和对阵列的支持。它是原始指针的容器。它明确地防止复制其包含的指针,就像正常赋值一样,也就是说,它只允许基础指针的一个所有者。 因此,当使用unique_ptr时,在任何一个资源中最多只能有一个unique_ptr,并且当该unique_ptr被销毁时,该资源将自动声明。此外,由于任何资源只能有一个unique_ptr,因此任何试图复制unique_ptr的尝试都会导致编译时错误。

 unique_ptr<A> ptr1 (new A);

 // Error: can't copy unique_ptr
 unique_ptr<A> ptr2 = ptr1;    

但是,可以使用新的移动语义移动unique_ptr,即使用std::move()函数将包含指针的所有权转移到另一个unique_ptr。

// Works, resource now stored in ptr2
unique_ptr<A> ptr2 = move(ptr1); 

所以,当我们想要一个指向某个对象的指针,并且当该指针被销毁时,该指针将被回收时,最好使用unique_ptr。

// C++ program to illustrate the use of unique_ptr
#include <iostream>
#include <memory>
using namespace std;
class A {
public :
void show()
{
cout << "A::show()" << endl;
}
};
int main()
{
unique_ptr<A> p1( new A);
p1->show();
// returns the memory address of p1
cout << p1.get() << endl;
// transfers ownership to p2
unique_ptr<A> p2 = move(p1);
p2->show();
cout << p1.get() << endl;
cout << p2.get() << endl;
// transfers ownership to p3
unique_ptr<A> p3 = move(p2);
p3->show();
cout << p1.get() << endl;
cout << p2.get() << endl;
cout << p3.get() << endl;
return 0;
}


输出:

A::show()
0x1c4ac20
A::show()
0          // NULL
0x1c4ac20
A::show()
0          // NULL
0          // NULL
0x1c4ac20

下面的代码返回一个资源,如果我们没有显式地捕获返回值,资源将被清除。如果我们这样做,那么我们就拥有该资源的专属所有权。通过这种方式,我们可以认为unique_ptr更安全、更好地替代auto_ptr。

unique_ptr<A> fun()
{
    unique_ptr<A> ptr(new A);

    /* ...
       ... */

    return ptr;
}

何时使用unique_ptr? 当您想拥有资源的单一所有权(独占)时,请使用unique_ptr。只有一个唯一的_ptr可以指向一个资源。由于单个资源可以有一个唯一的\u ptr,因此不可能将一个唯一的\u ptr复制到另一个。

共享ptr

共享的_ptr是原始指针的容器。这是一个 参考计数所有权模型 i、 e.它与共享ptr的所有副本合作,维护其包含指针的引用计数。因此,每当一个新指针指向资源时,计数器就会递增,而当调用对象的析构函数时,计数器就会递减。

参考计数: 它是一种存储资源(如对象、内存块、磁盘空间或其他资源)的引用、指针或句柄数量的技术。

包含的原始指针引用的对象将不会被销毁,直到引用计数大于零,即,直到所有共享的_ptr副本被删除。 所以,当我们想要将一个原始指针分配给多个所有者时,我们应该使用shared_ptr。

// C++ program to demonstrate shared_ptr
#include <iostream>
#include <memory>
using namespace std;
class A {
public :
void show()
{
cout << "A::show()" << endl;
}
};
int main()
{
shared_ptr<A> p1( new A);
cout << p1.get() << endl;
p1->show();
shared_ptr<A> p2(p1);
p2->show();
cout << p1.get() << endl;
cout << p2.get() << endl;
// Returns the number of shared_ptr objects
// referring to the same managed object.
cout << p1.use_count() << endl;
cout << p2.use_count() << endl;
// Relinquishes ownership of p1 on the object
// and pointer becomes NULL
p1.reset();
cout << p1.get() << endl;
cout << p2.use_count() << endl;
cout << p2.get() << endl;
return 0;
}


输出:

0x1c41c20
A::show()
A::show()
0x1c41c20
0x1c41c20
2
2
0          // NULL
1
0x1c41c20

何时使用共享ptr? 如果要共享资源的所有权,请使用shared_ptr。许多共享的ptr可以指向单个资源。shared_ptr维护此提议的参考计数。当指向资源的所有共享_ptr超出范围时,资源将被销毁。

弱ptr

弱_ptr被创建为共享_ptr的副本。它提供对一个或多个共享_ptr实例拥有的对象的访问,但不参与引用计数。弱_ptr的存在或破坏对共享_ptr或其其他副本没有影响。在某些情况下,需要中断共享_ptr实例之间的循环引用。

循环依赖性(共享ptr的问题): 让我们考虑一个场景,我们有两个类A和B,都有指向其他类的指针。所以,A总是指向B,B总是指向A。因此,use_计数永远不会达到零,它们永远不会被删除。

Circular reference for weak pointer

这就是我们使用 弱点 (弱_ptr),因为它们不是参考计数。因此,声明弱_ptr的类没有它的据点,即所有权不是共享的,但它们可以访问这些对象。

Circular reference for weak pointer

因此,在共享_ptr的情况下,由于循环依赖,use_count永远不会达到零,这是使用弱_ptr阻止的,弱_ptr通过将一个_ptr声明为弱_ptr来消除这个问题,因此类A不拥有它,只能访问它,我们还需要检查对象的有效性,因为它可能超出范围。一般来说,这是一个设计问题。

何时使用弱ptr? 当你确实想从多个地方引用你的对象时——对于那些可以忽略和取消分配的引用(所以当你尝试取消引用时,他们只会注意到对象已经消失)。

参考: https://www.quora.com/When-should-I-use-shared_ptr-and-unique_ptr-in-C++-它们有什么好处

本文由 希曼苏·古普塔(巴格里) .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。

如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享