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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16894400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:44:36  来源:igfitidea点击:

How to declare std::unique_ptr and what is the use of it?

c++pointersstdunique-ptr

提问by Roman

I try to understand how std::unique_ptrworks and for that I found thisdocument. The author starts from the following example:

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

What is confusing to me is that in this line

令我困惑的是,在这一行

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

We use integer as an argument (between round brackets) and here

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

unique_ptr<double> uptr2 (pd);

we used an pointer as an argument. Does it make any difference?

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

What is also not clear to me, is how pointers, declared in this way will be different from the pointers declared in a "normal" way.

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

回答by Andy Prowl

The constructor of unique_ptr<T>accepts a raw pointer to an object of type T(so, it accepts a T*).

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

In the first example:

在第一个例子中:

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

The pointer is the result of a newexpression, while in the second example:

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

unique_ptr<double> uptr2 (pd);

The pointer is stored in the pdvariable.

指针存储在pd变量中。

Conceptually, nothing changes (you are constructing a unique_ptrfrom a raw pointer), but the second approach is potentially more dangerous, since it would allow you, for instance, to do:

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

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

Thus having twounique pointers that effectively encapsulate the same object (thus violating the semantics of a uniquepointer).

因此有两个唯一的指针可以有效地封装同一个对象(从而违反了唯一指针的语义)。

This is why the first form for creating a unique pointer is better, when possible. Notice, that in C++14 we will be able to do:

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

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

Which is both clearer and safer. Now concerning this doubt of yours:

哪个更清晰,更安全。现在关于你的这个疑问:

What is also not clear to me, is how pointers, declared in this way will be different from the pointers declared in a "normal" way.

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

Smart pointers are supposed to model object ownership, and automatically take care of destroying the pointed object when the last (smart, owning) pointer to that object falls out of scope.

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

This way you do not have to remember doing deleteon objects allocated dynamically - the destructor of the smart pointer will do that for you - nor to worry about whether you won't dereference a (dangling) pointer to an object that has been destroyed already:

通过这种方式,您不必记住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

Now unique_ptris a smart pointer that models unique ownership, meaning that at any time in your program there shall be only one(owning) pointer to the pointed object - that's why unique_ptris non-copyable.

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

As long as you use smart pointers in a way that does not break the implicit contract they require you to comply with, you will have the guarantee that no memory will be leaked, and the proper ownership policy for your object will be enforced. Raw pointers do not give you this guarantee.

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

回答by fury.slay

There is no difference in working in both the concepts of assignment to unique_ptr.

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

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

is similar to

类似于

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

Here unique_ptrautomatically deletes the space occupied by uptr.

这里unique_ptr 会自动删除uptr.



how pointers, declared in this way will be different from the pointers declared in a "normal" way.

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

If you create an integer in heap space (using newkeyword or malloc), then you will have to clear that memory on your own (using deleteor freerespectively).

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

In the below code,

在下面的代码中,

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

Here, you will have to deleteheapInt, when it is done using. If it is not deleted, then memory leakage occurs.

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


In order to avoid such memory leaks unique_ptris used, where unique_ptr automatically deletes the space occupied by heapInt when it goes out of scope.


为了避免这种内存泄漏,使用了unique_ptr,其中unique_ptr在超出范围时会自动删除heapInt占用的空间。

回答by fatihk

Unique pointers are guaranteed to destroy the object they manage when they go out of scope. http://en.cppreference.com/w/cpp/memory/unique_ptr

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

In this case:

在这种情况下:

unique_ptr<double> uptr2 (pd);

pdwill be destroyed when uptr2goes out of scope. This facilitates memory management by automatic deletion.

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

The case of unique_ptr<int> uptr (new int(3));is not different, except that the raw pointer is not assigned to any variable here.

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