动态内存
- 12.1 动态内存与智能指针
- shared_ptr类
对象的生存周期
对象类型 | 生存周期 |
---|---|
全局对象 | 创建:程序启动时。 销毁:程序结束时。 |
局部自动对象 | 创建:进入其定义所在的程序块时。 销毁:离开其定义所在的程序块时。 |
局部static对象 | 创建:第一次使用之前。 销毁:程序结束时。 |
动态分配对象 | 创建:手动创建。 销毁:手动销毁。 |
为什么使用智能指针?
动态对象的正确释放被证明是编程中极其容易出错的地方。为了更安全且容易地使用动态对象,标准库定义了两个智能指针类型来管理动态分配的对象。当一个对象应该被释放时,指向它的智能指针可以确保自动地释放它。
对象的内存空间
对象类型 | 内存空间 |
---|---|
局部 static 对象 | 静态内存 |
类 static 数据成员 | 静态内存 |
全局变量 | 静态内存 |
类内非 static 对象 | 栈内存 |
动态分配对象 | 堆内存 |
分配在静态或栈内存中的对象由编译器自动创建和销毁。
分配在堆内存中的对象由程序来控制。
12.1 动态内存与智能指针
在C++中,动态内存的管理是通过一对运算符来完成的:
- new,在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化;
- delete,接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。
代码演示:使用new 创建对象并进行初始化以及使用 delete 释放对象。
#include <iostream>using namespace std;int main()
{//使用 new 在动态内存中为 int 类型对象分配空间并进行初始化。int* p = new int(10); cout << *p << endl;//释放内存空间delete p;return 0;
}
运行结果:
代码演示:内存泄露。
#include <iostream>using namespace std;int main()
{//使用 new 在动态内存中为 int 类型对象分配空间并进行初始化。int* p = new int(10); cout << *p << endl;//new 申请的动态内存未释放,内存泄漏。//delete p;return 0;
}
代码演示:引用非法内存的指针。
#include <iostream>using namespace std;int main()
{//使用 new 在动态内存中为 int 类型对象分配空间并进行初始化。int* p = new int(10); delete p;p = nullptr;//new 申请的动态内存已经释放,产生引用非法内存*p = 66;cout << *p << endl;return 0;
}
新标准库(C++11)提供两种智能指针类型来管理动态对象:
智能指针类型 | 区别 |
---|---|
shared_ptr | 允许多个 shared_ptr 指针指向同一对象。 |
unique_ptr | 只允许一个 unique_ptr 独占所指向的对象 |
智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。
类型所在头文件:#include<memory>
shared_ptr类
智能指针是模板,创建一个智能指针时必须提供指针可以指向的类型。
shared_ptr<string> p1; //shared_ptr 可以指向 string 对象
shared_ptr<vector<int>> p2; //shared_ptr 可以指向 vector<int> 对象
默认初始化的智能指针中保存着一个空指针。
代码演示:默认初始化的智能指针中保存着一个空指针。
#include <iostream>
#include <memory>
#include <string>
using namespace std;int main()
{shared_ptr<string> p1; //shared_ptr 可以指向 string 对象if (nullptr == p1){cout << "nullptr == p1" << endl;}else{cout << "nullptr != p1" << endl;}return 0;
}
运行结果:
代码演示:智能指针解引用。
#include <iostream>
#include <memory>
#include <string>
#include <vector>
using namespace std;int main()
{shared_ptr<string> p1 = make_shared<string>("helloworld"); //创建shared_ptr指针并生成对象进行初始化cout << *p1 << endl;return 0;
}
运行结果:
智能指针作为条件判断:
智能指针指向一个对象,返回 true。
智能指针指向空指针,返回false。
代码演示:
#include <iostream>
#include <memory>
#include <string>
#include <vector>
using namespace std;int main()
{shared_ptr<string> p1; //shared_ptr 可以指向 string 对象if (p1){cout << "nullptr != p1" << endl;}else{cout << "nullptr == p1" << endl;}return 0;
}
运行结果:
p->mem
等价于 (*p).mem
代码演示:
#include <iostream>
#include <memory>
#include <string>
#include <vector>
using namespace std;int main()
{shared_ptr<string> p1 = make_shared<string>("helloworld"); //创建shared_ptr指针并生成对象进行初始化if (!p1->empty()){cout << *p1 << endl;}if(!(*p1).empty()){cout << *p1 << endl;}return 0;
}
运行结果:
说明:返回 p 中保存的指针。
注意:智能指针释放,p.get() 返回的指针所指向的对象也消失。
代码演示:
#include <iostream>
#include <memory>
#include <string>
#include <vector>
using namespace std;int main()
{string* p2 = nullptr;if (p2){cout << "p2 = " << *p2 << endl;}else{cout << "nullptr = p2" << endl;}{shared_ptr<string> p1 = make_shared<string>("helloworld"); //创建shared_ptr指针并生成对象进行初始化string* p2 = p1.get();if (p2){cout << "p2 = " << *p2 << endl;}else{cout << "null = p2" << endl;}//智能指针释放,p.get() 返回的指针所指向的对象也消失。}if (p2){cout << "p2 = " << *p2 << endl;}else{cout << "nullptr = p2" << endl;}return 0;
}
运行结果: