一、三种智能指针
- auto_ptr
- unique_ptr
- shared_ptr
(auto_ptr是C++98提供的方案,C++11已经将其摒弃,以下只是示例,实际不要使用auto_ptr)
使用new和delete管理动态内存常出现的问题: (1)忘记delete内存 (2)使用已经释放的对象 (3)同一块内存释放两次
这三种智能指针模板都定义了类似指针的对象,可以将new获得的地址赋给这种对象。当智能指针过期时,其析构函数将使用delete释放内存(内存被自动释放,无需手动delete)。
- 智能指针模板位于名称空间中。
- 要创建智能指针,必须包含头文件memory
二、使用智能指针
- 可以对智能指针执行解引用操作( *ptr );
- 可以用它来访问结构成员(ps->next);
- 将它赋给指向相同类型的常规指针;
- 将智能指针对象赋给另一个同类型的智能指针对象时需要注意(unique_ptr和shared_ptr不同,下面会讲)
auto_ptr<typename> pd(new typename);
auto_ptr<double> pd(new double);
auto_ptr<string> pd(new string);
其中 new typename 是new返回的指针,指向新分配的内存块,是构造函数auto_ptr<double> 的参数。
#include <iostream>
#include <string>
#include <memory>
using namespace std;
class Report{
private:
string str;
public:
Report(const string s) : str(s){
cout<<"Object created! \n";
}
~Report(){
cout<<"Object deleted!\n";
}
void comment() const{ cout<<str<<"\n";}
};
int main(){
{
auto_ptr<Report> ps(new Report("uing auto_ptr"));
ps->comment();
}
{
shared_ptr<Report> ps(new Report("uing shared_ptr"));
ps->comment();
}
{
unique_ptr<Report> ps(new Report("suing unique_ptr"));
ps->comment();
}
}
输出如下: 注意
- 所有指针都有一个explicit构造函数,该构造函数将指针作为参数。因此一下操作是不合法的:
shared_ptr<double> pd;
double* p =new double;
pd = p_reg;
shared_ptr<double> pshared = p_reg;
pd = shared_ptr<double>(preg);
shared_pte<double> pshared(p_reg);
- 不要用指向非堆内存的指针初始化智能指针对象,因为这将导致delete释放非堆内存,这是错误的。
string vacation("I love you.");
shared_ptr<string> pd(&vacation);
三、unique_ptr指针
unique_ptr指针使用所有权模型,即对于特定的对象,只能由一个智能指针可拥有它,只有拥有对象的智能指针的构造函数会删除该对象。
unique_ptr<string> p1(new string("auto"));
unique_ptr<string> p2;
p2=p3;
第三句会报错,编译器认为其非法。因为p2接管string对象后,p1的所有权将被剥夺,也就是p1不再指向有效数据。如果程序随后试图使用p1,将会发生问题。
但如果源unique_ptr是个临时右值,编译器允许这样做, 语句#2调用unique_ptr的构造函数的创建临时对象在将其所有权转让给pu3后就会被销毁。 C++的标准库函数std::move()让您能够将unique_ptr赋给另一个
四、shared_ptr指针
shared_ptr指针可以跟踪引用特定对象的智能指针数,赋值时,计数将+1,而指针过期时,计数-1。仅当最后一个指针过期时,才调用delete。 shared_ptr指针允许多个智能指针指向同一个对象。
五、选择智能指针
- 如果程序要使用多个指向同一个对象的指针,应选择shared_ptr
- 如果程序不需要多个指向同一个对象的指针,则可使用unique_ptr。
unique_ptr
- 不使用new 或 new[ ] 分配内存时,不能使用unique_ptr
shared_ptr
- 使用new分配内存时,才能使用shared_ptr
- 使用new[ ]时,不能使用它
- 不使用new分配内存时,不能使用它
|