什么是智能指针,什么时候应该使用?
当前回答
智能指针类似于常规(类型化)指针,如“char*”,除非指针本身超出范围,否则它所指向的内容也会被删除。您可以像使用常规指针一样使用它,方法是使用“->”,但如果您需要指向数据的实际指针,则不需要。为此,可以使用“&*ptr”。
它适用于:
对象必须分配新的,但您希望与堆栈中的对象具有相同的生存期。如果对象被分配给智能指针,那么当程序退出该函数/块时,它们将被删除。类的数据成员,因此当对象被删除时,所有拥有的数据也会被删除,而析构函数中没有任何特殊代码(您需要确保析构函数是虚拟的,这几乎总是一件好事)。
在以下情况下,您可能不想使用智能指针:
…指针实际上不应该拥有数据。。。即,当您只是在使用数据,但希望它在引用它的函数中生存时。…智能指针本身不会在某个时刻被破坏。您不希望它位于永远不会被破坏的内存中(例如动态分配但不会显式删除的对象中)。…两个智能指针可能指向相同的数据。(然而,还有更聪明的指针可以处理这一点……这就是所谓的引用计数。)
另请参见:
垃圾收集。关于数据所有权的堆栈溢出问题
其他回答
智能指针是一个类,是普通指针的包装。与普通指针不同,智能指针的生命周期基于引用计数(智能指针对象被分配的次数)。因此,每当智能指针分配给另一个指针时,内部引用计数加上。每当对象超出范围时,引用计数减。
自动指针,虽然看起来类似,但与智能指针完全不同。这是一个方便的类,每当自动指针对象超出变量范围时,它就释放资源。在某种程度上,它使指针(指向动态分配的内存)的工作方式类似于堆栈变量(在编译时静态分配)。
让T成为本教程中的一个班级C++中的指针可以分为3种类型:
1) 原始指针:
T a;
T * _ptr = &a;
它们将内存地址保存到内存中的某个位置。小心使用,因为程序变得复杂,难以跟踪。
具有常量数据或地址的指针{向后读取}
T a ;
const T * ptr1 = &a ;
T const * ptr1 = &a ;
指向作为常量的数据类型T的指针。这意味着不能使用指针更改数据类型。ie*ptr1=19;不会起作用。但是你可以移动指针。即ptr1++、ptr1--;等等都会起作用。向后读取:指向类型T(常量)的指针
T * const ptr2 ;
指向数据类型T的常量指针。这意味着不能移动指针,但可以更改指针指向的值。ie*ptr2=19将工作,但ptr2++;ptr2等将不起作用。向后读取:指向T类型的常量指针
const T * const ptr3 ;
指向常量数据类型T的常量指针。这意味着您既不能移动指针,也不能将数据类型指针更改为指针。即。ptr3--;ptr3++*ptr3=19;不起作用
3) 智能指针:{#include<memory>}
共享指针:
T a ;
//shared_ptr<T> shptr(new T) ; not recommended but works
shared_ptr<T> shptr = make_shared<T>(); // faster + exception safe
std::cout << shptr.use_count() ; // 1 // gives the number of "
things " pointing to it.
T * temp = shptr.get(); // gives a pointer to object
// shared_pointer used like a regular pointer to call member functions
shptr->memFn();
(*shptr).memFn();
//
shptr.reset() ; // frees the object pointed to be the ptr
shptr = nullptr ; // frees the object
shptr = make_shared<T>() ; // frees the original object and points to new object
使用引用计数实现,以跟踪有多少“东西”指向指针指向的对象。当此计数为0时,对象将自动删除,即当指向对象的所有share_ptr超出范围时,对象被删除。这消除了必须删除使用new分配的对象的麻烦。
弱指针:帮助处理使用共享指针时出现的循环引用如果有两个对象被两个共享指针指向,并且有一个内部共享指针指向其他共享指针,则会有一个循环引用,当共享指针超出范围时,不会删除该对象。要解决此问题,请将内部成员从shared_ptr更改为weak_ptr。注意:要访问弱指针指向的元素,请使用lock(),这将返回一个weak_ptr。
T a ;
shared_ptr<T> shr = make_shared<T>() ;
weak_ptr<T> wk = shr ; // initialize a weak_ptr from a shared_ptr
wk.lock()->memFn() ; // use lock to get a shared_ptr
// ^^^ Can lead to exception if the shared ptr has gone out of scope
if(!wk.expired()) wk.lock()->memFn() ;
// Check if shared ptr has gone out of scope before access
请参见:std::weak_ptr何时有用?
唯一指针:拥有独家所有权的轻质智能指针。当指针指向唯一对象而不在指针之间共享对象时使用。
unique_ptr<T> uptr(new T);
uptr->memFn();
//T * ptr = uptr.release(); // uptr becomes null and object is pointed to by ptr
uptr.reset() ; // deletes the object pointed to by uptr
要更改唯一ptr指向的对象,请使用移动语义
unique_ptr<T> uptr1(new T);
unique_ptr<T> uptr2(new T);
uptr2 = std::move(uptr1);
// object pointed by uptr2 is deleted and
// object pointed by uptr1 is pointed to by uptr2
// uptr1 becomes null
参考文献:它们本质上可以被认为是常量指针,即常量指针,不能用更好的语法移动。
参见:C++中指针变量和引用变量之间的区别是什么?
r-value reference : reference to a temporary object
l-value reference : reference to an object whose address can be obtained
const reference : reference to a data type which is const and cannot be modified
参考:https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ 感谢安德烈指出了这个问题。
智能指针是那些你不必担心内存取消分配、资源共享和传输的地方。
您可以很好地使用这些指针,其方式与Java中的任何分配方式类似。在java垃圾收集器中完成了这一任务,而在智能指针中,这一任务由Destructor完成。
智能指针是一种类似指针的对象,但它还提供了对构造、销毁、复制、移动和取消引用的控制。
人们可以实现自己的智能指针,但许多库也提供智能指针实现,每个实现都有不同的优点和缺点。
例如,Boost提供了以下智能指针实现:
shared_ptr<T>是一个指向T的指针,它使用引用计数来确定何时不再需要对象。scoped_ptr<T>是一个在超出范围时自动删除的指针。无法分配。intrusive_ptr<T>是另一个引用计数指针。它提供了比shared_ptr更好的性能,但需要类型T提供自己的引用计数机制。weak_ptr<T>是一个弱指针,与shared_ptr一起工作以避免循环引用。shared_array<T>类似于shared_ptr,但对于T的数组。scoped_array<T>类似于scoped_ptr,但对于T的数组。
这些只是对每一个的一个线性描述,可以根据需要使用,有关更多细节和示例,可以查看Boost的文档。
此外,C++标准库提供了三个智能指针;std::unique_ptr表示唯一所有权,std::shared_ptr表示共享所有权,std::weak_ptr表示共享所有权。std::auto_ptr在C++03中存在,但现在已弃用。
Chris、Sergdev和Llyod提供的定义是正确的。我更喜欢一个更简单的定义,只是为了让我的生活简单:智能指针只是一个重载->和*运算符的类。这意味着你的对象在语义上看起来像一个指针,但你可以让它做一些更酷的事情,包括引用计数、自动销毁等。sharedptr和autoptr在大多数情况下都是足够的,但它们也有自己的一些小特点。