119

我试图了解它是如何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);

我们使用指针作为参数。它有什么不同吗?

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

4

4 回答 4

111

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

在第一个示例中:

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

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

unique_ptr<double> uptr2 (pd);

指针存储在pd变量中。

从概念上讲,没有任何变化(您正在unique_ptr从原始指针构造 a ),但第二种方法可能更危险,因为它允许您执行以下操作:

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就是不可复制的原因。

只要您以不破坏它们要求您遵守的隐式合同的方式使用智能指针,您就可以保证不会泄漏任何内存,并且将为您的对象执行适当的所有权策略。原始指针不给你这个保证。

于 2013-06-03T10:18:03.253 回答
22

在分配给 unique_ptr 的两个概念中工作没有区别。

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

类似于

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

这里unique_ptr会自动删除uptr.


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

如果您在堆空间中创建一个整数(使用new关键字或malloc),那么您将必须自己清除该内存(分别使用deletefree)。

在下面的代码中,

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

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

为了避免这种内存泄漏,使用了unique_ptr,其中 unique_ptr 在超出范围时会自动删除 heapInt 占用的空间。因此,您无需为 unique_ptr执行删除释放操作。

于 2017-02-06T04:33:34.123 回答
13

唯一指针保证在超出范围时销毁它们管理的对象。 http://en.cppreference.com/w/cpp/memory/unique_ptr

在这种情况下:

unique_ptr<double> uptr2 (pd);

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

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

于 2013-06-03T10:15:39.677 回答
2

cppreferencestd::unique_ptr构造函数之一是

显式 unique_ptr( 指针 p ) noexcept;

所以创建一个新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;

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

于 2020-07-08T13:43:50.487 回答