如何声明 std: : special_ptr 以及它的用途是什么?

我试图了解 std::unique_ptr是如何工作的,为此我找到了 这个文档。作者从以下例子开始:

#include <utility>  //declarations of unique_ptr
using std::unique_ptr;
// default construction
unique_ptr<int> up; //creates an empty object
// initialize with an argument
unique_ptr<int> uptr (new int(3));
double *pd= new double;
unique_ptr<double> uptr2 (pd);
// overloaded * and ->
*uptr2 = 23.5;
unique_ptr<std::string> ups (new std::string("hello"));
int len=ups->size();

让我困惑的是,在这条线上

unique_ptr<int> uptr (new int(3));

我们使用整数作为参数(在圆括号之间) ,这里

unique_ptr<double> uptr2 (pd);

我们使用了一个指针作为参数。这有什么区别吗?

我也不清楚的是,以这种方式声明的指针与以“正常”方式声明的指针如何不同。

187105 次浏览

当唯一指针超出作用域时,它们保证会销毁所管理的对象。 Http://en.cppreference.com/w/cpp/memory/unique_ptr

在这种情况下:

unique_ptr<double> uptr2 (pd);

uptr2超出范围时,pd将被销毁。这有助于通过自动删除来管理内存。

unique_ptr<int> uptr (new int(3));的情况没有什么不同,除了原始指针没有指派给这里的任何变量。

unique_ptr<T>的构造函数接受指向类型为 T的对象的原始指针(因此,它接受 T*)。

在第一个例子中:

unique_ptr<int> uptr (new int(3));

指针是 new表达式的结果,而在第二个示例中:

unique_ptr<double> uptr2 (pd);

指针存储在 pd变量中。

从概念上讲,没有什么变化(您正在从一个原始指针构造一个 unique_ptr) ,但是第二种方法可能更危险,因为它将允许您,例如,执行:

unique_ptr<double> uptr2 (pd);
// ...
unique_ptr<double> uptr3 (pd);

这样就有了 唯一的指针,有效地封装了同一个对象(从而违反了 独一无二指针的语义)。

这就是为什么在可能的情况下,创建唯一指针的第一种形式更好。注意,在 C + + 14中,我们可以做到:

unique_ptr<int> p = make_unique<int>(42);

这样更清楚也更安全,关于你的这个疑问:

我也不清楚的是,以这种方式声明的指针与以“正常”方式声明的指针如何不同。

智能指针应该为对象所有权建模,并在指向该对象的最后一个(智能的、拥有的)指针超出范围时自动销毁指向的对象。

这样,你就不必记得对动态分配的对象执行 delete操作——智能指针的析构函数会为你执行这个操作——也不必担心你是否会解引用一个(悬空的)指针到一个已经被销毁的对象:

{
unique_ptr<int> p = make_unique<int>(42);
// Going out of scope...
}
// I did not leak my integer here! The destructor of unique_ptr called delete

现在,unique_ptr是一个智能指针,模型唯一的所有权,这意味着在任何时候,在您的程序应该只有 (拥有)指针指向指向的对象-这就是为什么 unique_ptr是不可复制的。

只要您使用智能指针的方式不违反它们要求您遵守的隐式约定,您就可以保证不会泄漏内存,并且将强制执行对象的适当所有权策略。原始指针不能保证这一点。

在这两个概念中,对 only _ ptr 的赋值没有什么不同。

int* intPtr = new int(3);
unique_ptr<int> uptr (intPtr);

类似于

unique_ptr<int> uptr (new int(3));

这里,Unique _ ptr自动删除 uptr所占用的空间。


以这种方式声明的指针如何与以“正常”方式声明的指针不同。

如果在堆空间中创建一个整数(使用 新的关键字或 Malloc) ,那么必须自己清除该内存(分别使用 删除自由)。

在下面的代码中,

int* heapInt = new int(5);//initialize int in heap memory
.
.//use heapInt
.
delete heapInt;

在这里,您必须使用 删除 heapInt。如果不删除它,则会发生内存泄漏。

为了避免这种内存泄漏,我们使用了 Unique _ ptr,当某个内存泄漏超出作用域范围时,special _ ptr 会自动删除 heapInt 所占用的空间。因此,您不需要为 only _ ptr 执行 删除自由操作。

首选开始,std::unique_ptr构造函数之一是

显式的 only _ ptr (指针 p)不除外;

因此,创建一个新的 std::unique_ptr就是传递一个指向其构造函数的指针。

unique_ptr<int> uptr (new int(3));

或者和

int *int_ptr = new int(3);
std::unique_ptr<int> uptr (int_ptr);

不同的是,你不必清理后使用它。如果您不使用 std::unique_ptr(智能指针) ,您将不得不像这样删除它

delete int_ptr;

当您不再需要它时,它会导致内存泄漏。