智能指针介绍
当我们在使用new
动态分配内存时,有时候会忘记将分配的内存释放,例如,一个常规指针p,当p过期时p占据的内存将被释放,如果此前没有调用delete释放p指向的内存,就会导致内存泄漏。
如果指针p是一个对象的话,那么就能够在p被删除时,调用它的析构函数去释放p指向的内存,从而简化了动态内存管理,这就是智能指针的思想。
使用智能指针
在头文件memory中定义了智能指针模板类:auto_ptr,unique_ptr,shared_ptr
。(auto_ptr
在C++11中被摒弃)
shared_ptr
有一个如下构造函数,接受一个指针作为参数:
template <class U>
explicit shared_ptr (U* p)
因此可以将new获得的地址,赋值给智能指针对象,来创建一个智能指针:
shared<string> p(new string);
此构造函数为explicit所以不支持隐式转换:
shared<string> p;
string* s = new string;
p = s //隐式转换不支持,这是错误的
智能指针的操作与常规指针类似,使用(*p),下面为智能指针使用演示程序:
class Person {
private:
std::string name;
public:
Person(const std::string& s):name(s){}
~Person() { std::cout << "Object delete" << std::endl; }
void view()const { std::cout << "Name: " << name << std::endl; }
};
int main() {
{
std::shared_ptr<Person> ps(new Person("Tom"));
ps->view();
}
{
std::unique_ptr<Person> pu(new Person("Bob"));
pu->view();
}
}
result.png
当智能指针过期时,调用了它的析构函数,来释放Person对象。
智能指针使用注意事项
现在考虑两个智能指针指向同一块内存的情况,当两个指针都过期时,程序将释放同一块内存两次。
为解决这个问题shared_ptr
采用以下措施:
跟踪引用特定对象的智能指针数(引用计数)。仅当最后一个指针过期时,才调用delete。
unique_ptr
的解决方案:
建立所有权概念,对于特定的对象,只有一个智能指针可以拥有它,只有拥有对象的智能指针才可以释放它。并且,赋值操作将转让所有权,转让所有权后指针不再指向有效数据。这个过程将会非常严格。
下面是unique_ptr
处理此问题的两个例子:
unique_ptr<string> p1(new string("unique")); //#1
unique_ptr<string> p2; //#2
p2 = p1; //#3 非法语句
对于上述例子,转让所有权后p1将不再指向有效数据,为了避免p1不再指向有效数据,对于语句#3编译器将会认为是非法的
假设又如下函数定义:
unique_ptr<string> demo(){
std::unique_ptr<string> p(new string("dome"));
return p;
}
unique_ptr<string> p2;
p2 = demo();
这时p2 = demo()将是合法的赋值操作,因为demo返回一个临时对象,赋值完成后将被销毁。
网友评论