如何声明std::unique_ptr以及它的用途

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

本文关键字:ptr unique 何声明 声明 std      更新时间:2023-10-16

我试图了解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));

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

unique_ptr<double> uptr2 (pd);

使用指针作为实参。这有什么区别吗?

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

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

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

对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,当heapInt超出作用域时,unique_ptr会自动删除它所占用的空间。因此,您不需要为unique_ptr执行deletefree

唯一指针保证在超出作用域时销毁其管理的对象。http://en.cppreference.com/w/cpp/memory/unique_ptr

在本例中:

unique_ptr<double> uptr2 (pd);
uptr2超出作用域时,

pd将被销毁。通过自动删除,方便了内存管理。

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

从cppreference中,有一个std::unique_ptr构造函数是

因此,创建一个新的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;

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