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

Rom*_*man 76 c++ pointers std unique-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();
Run Code Online (Sandbox Code Playgroud)

令我困惑的是,在这一行

unique_ptr<int> uptr (new int(3));
Run Code Online (Sandbox Code Playgroud)

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

unique_ptr<double> uptr2 (pd);
Run Code Online (Sandbox Code Playgroud)

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

对我来说还不清楚的是,以这种方式声明的指针将如何与以"正常"方式声明的指针不同.

And*_*owl 72

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

在第一个例子中:

unique_ptr<int> uptr (new int(3));
Run Code Online (Sandbox Code Playgroud)

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

unique_ptr<double> uptr2 (pd);
Run Code Online (Sandbox Code Playgroud)

指针存储在pd变量中.

从概念上讲,没有任何变化(你正在unique_ptr从原始指针构造一个),但第二种方法可能更危险,因为它允许你,例如,做:

unique_ptr<double> uptr2 (pd);
// ...
unique_ptr<double> uptr3 (pd);
Run Code Online (Sandbox Code Playgroud)

因此,有两个唯一的指针有效地封装了同一个对象(因此违反了唯一指针的语义).

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

unique_ptr<int> p = make_unique<int>(42);
Run Code Online (Sandbox Code Playgroud)

哪个更清晰,更安全.现在关于你的怀疑:

对我来说还不清楚的是,以这种方式声明的指针将如何与以"正常"方式声明的指针不同.

智能指针应该模拟对象所有权,并且当指向该对象的最后一个(智能,拥有)指针超出范围时,自动处理销毁指向对象.

这样你就不必记住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
Run Code Online (Sandbox Code Playgroud)

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

只要您使用智能指针的方式不会违反它们要求您遵守的隐式契约,您就可以保证不会泄漏任何内存,并且将强制执行对象的正确所有权策略.原始指针不会给你这个保证.

  • 嗨,我无法理解"模型对象所有权",代码中的"整数泄漏"或"强制执行对象的所有权政策".您能否建议主题/资源来学习这些概念? (2认同)

fur*_*lay 12

赋值给unique_ptr的两个概念都没有区别.

int* intPtr = new int(3);
unique_ptr<int> uptr (intPtr);
Run Code Online (Sandbox Code Playgroud)

类似于

unique_ptr<int> uptr (new int(3));
Run Code Online (Sandbox Code Playgroud)


如何以这种方式声明的指针将与以"正常"方式声明的指针不同.

如果在堆空间中创建一个整数(使用new keyword或malloc),则必须自己清除该内存(分别使用deletefree).

在下面的代码中,

int* heapInt = new int(5);//initialize int in heap memory
.
.//use heapInt
.
delete heapInt;
Run Code Online (Sandbox Code Playgroud)

在这里,你必须删除 heapInt,完成后使用.如果未删除,则会发生内存泄漏.
为了避免这种内存泄漏,使用unique_ptr,其中unique_ptr会在超出范围时自动删除heapInt占用的空间.


fat*_*ihk 7

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

在这种情况下:

unique_ptr<double> uptr2 (pd);
Run Code Online (Sandbox Code Playgroud)

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

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