我试着理解std::unique_ptr
是如何工作的,为此我找到了this文件。作者从以下示例开始:
#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);
我们使用指针作为参数。它有什么不同吗?
对我来说还不清楚的是,以这种方式声明的指针将如何与以“正常”方式声明的指针不同。
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 keyword或malloc),则必须自己清除该内存(分别使用delete或free)。
在下面的代码中,
int* heapInt = new int(5);//initialize int in heap memory
.
.//use heapInt
.
delete heapInt;
在这里,你必须删除heapInt,完成后使用。如果未删除,则会发生内存泄漏。
为了避免这种内存泄漏,使用unique_ptr,其中unique_ptr会在超出范围时自动删除heapInt占用的空间。
保证唯一指针在超出范围时销毁它们管理的对象。 http://en.cppreference.com/w/cpp/memory/unique_ptr
在这种情况下:
unique_ptr<double> uptr2 (pd);
当pd
超出范围时,uptr2
将被销毁。这通过自动删除来促进存储器管理。
unique_ptr<int> uptr (new int(3));
的情况没有什么不同,除了原始指针没有分配给任何变量。