xx智能指针:防止用户忘记释放掉指针所指的堆空间而造成内存泄漏
当一个对象应该被释放时,指向它的智能指针可以确保自动地释放它
智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。C++ 11中最常用的智能指针类型为shared_ptr,它采用引用计数的方法,记录当前内存资源被多少个智能指针引用。该引用计数的内存在堆上分配。当新增一个时引用计数加1,当过期时引用计数减一。只有引用计数为0时,智能指针才会自动释放引用的内存资源。对shared_ptr进行初始化时不能将一个普通指针直接赋值给智能指针,因为一个是指针,一个是类。可以通过make_shared函数或者通过构造函数传入普通指针。并可以通过get函数获得普通指针。
手动释放空间new和delete类名 *指针名 = new 类名(参数)
...
delete 指针
析构函数被执行才能说明内存释放成功
具体实例1.1
#include
using namespace std;
class Human {
public:
Human(string name_ = "martin", int age_ = 30) :name(name_), age(age_) { }
void greet() {
cout << "Hi, how are you? I am " << name << "." << endl;
}
// 析构函数,如果不定义,系统会默认有一个构造函数
~Human() {
cout << name << " is gone!" << endl;
}
private:
string name;
int age;
};
int main() {
// 情况1:不使用指针 A在栈空间
Human A("meteorsh", 20);
A.greet();
// 情况2:使用指针 p在栈空间,但对象Human("daniel", 18)在堆空间
Human* p = new Human("daniel", 18);
(*p).greet();
return 0;
}
输出:
Hi, how are you? I am meteorsh.
Hi, how are you? I am daniel.
meteorsh is gone!
解释
从输出可以看到程序会自动释放栈空间的内容,对象A和指针p都被释放了,但是指针p所指的对象Human(“daniel”, 18)在堆空间中,因为我们未使用delete释放这部分内存,所以会造成内存泄漏
题外话
delete的本质:析构函数+C语言的free()函数,作用是销毁对象,并释放与之关联的内存
如果在情况2最后加上delete p
// 情况2:使用指针 p在栈空间,但临时对象Human("daniel", 18)在堆空间
Human* p = new Human("daniel", 18);
(*p).greet();
delete p;
则输出结果为
Hi, how are you? I am meteorsh.
Hi, how are you? I am daniel.
daniel is gone!
meteorsh is gone!
注意:此时Human(“daniel”, 18)比A先被析构
动态指针动态对象的正确释放被证明是编程中极其容易出错的地方,所以为了更加安全地使用动态对象,C++11引入了几个智能指针
auto_ptr (已被C++摒弃) unique_ptr (独占所指对象) shared_ptr (允许多个指针指向同一个对象) weak_ptr (一种弱引用)上述指针的头文件都是
智能指针(将普通指针封装成一个栈对象)
当一个对象应该被释放时,指向它的智能指针可以确保自动地释放它
类似vector等模版,智能指针也是模版(类模版) C++模版介绍
shared_ptr p1;
// 类似 swap (int a, int b)
// 或 vector vec;
默认初始化的智能指针中保留着一个空指针
(1)make_shared函数
此函数在动态内存中分配一个对象并初始化它,返回一个指向此对象的
shared_ptr指针
shared_ptr p3 = make_shared(3)
紧接着上面具体实例1.1
...
// 情况3:智能指针(将普通指针封装成一个栈对象)
shared_ptr p3 = make_shared("kevin", 18);
auto p4 = make_shared (2);
(*p3).greet();
输出
...
Hi, how are you? I am kevin.
kevin is gone!
下面的用法是不对的,因为new返回的是一个普通指针
shared_ptr p3 = new Human("kevin", 18);
Wrong
但是可以这样初始化智能指针
shared_ptr p3(new Human("kevin", 18));
当指向一个对象的最后一个shared_ptr被销毁时,shared_ptr类会自动销毁(它是通过析构函数完成销毁工作的)
shared_ptr的析构函数会递减它所指向的对象的引用计数,如果引用计数变为0,shared_ptr的析构函数就会销毁对象,并释放它所占用的空间
——参考C++ primer P453