引言
new 分配的内存块与常规变量声明分配的内存块不同,常规变量声明分配的内存在被称为栈的内存区域中,而new在被称为堆(也称自由存储区)的内存区域分配内存。
直接声明的对象,比如 BinNode a,即在栈上面的对象,所在作用域结束后,栈空,然后会自动执行析构函数,而new创建出来的是在堆上的对象,如果不调用delete,即使它所在的作用域已经结束,也不会调用析构函数。系统os 会在程序结束,回收该部分内存。
简介
auto_ptr、unique_ptr、shared_ptr 这三个智能指针模版都定义了类似指针的对象,可以将new获得的地址赋值给这种对象。当智能指针过期时,会自动调用指针对象的析构函数,再释放堆中内存。其也相当于等价delete操作。也就是说,delete语句的本质是调用指针对象自身的析构函数,再释放内存。与之对应,new的本质是先在堆上分配内存,再调用对象的构造函数。
所有权概念: 对于特定的对象,只能有一个智能指针拥有它,这样只有拥有对象所有权的智能指针的析构函数会删除该对象。(不适用于shared_ptr)
使用
要创建智能指针对象,必须包含头文件memory
。
- auto_ptr等三个智能指针都可以自动调用析构函数。
- auto_ptr已过时,不被推荐使用。
- unique_ptr 用于代替auto_ptr。其特点是不允许智能指针赋值,保护所有权。
- 如果程序要使用多个指向同一对象的指针,应选用shared_ptr。
代码实例
#include <iostream>
#include <memory>
#include <string>
class Report {
private:
std::string str;
public:
Report(const std::string s)
: str(s)
{
std::cout << "object created\n";
}
~Report() { std::cout << "object deleted!\n"; }
void comment() const { std::cout << str << "\n"; }
};
int main()
{
{
Report a(" not using new");
a.comment();
}
std::cout << "--------------------\n";
{ //加括号是为了限制定义域,出了定义域就应该删除内部临时变量。
Report* pr = new Report("using simple ptr"); // 发现一个知识,通过new 建立的内存块 是必须要用delete 语句来释放的,换而言之,其实,new 没有创建一个Report只是创建了一个Report* ,他是不会在程序结束后自动调用 其析构函数的。
pr->comment();
}
std::cout << "--------------------\n";
{
std::auto_ptr<Report> ps(new Report("using auto_ptr"));
ps->comment();
}
std::cout << "--------------------\n";
{
std::unique_ptr<Report> p(new Report("using unique_ptr"));
p->comment();
}
return 0;
}
输出
object created
not using new
object deleted!
--------------------
object created
using simple ptr 可以看出没有调用析构函数,当然也没有释放内存
--------------------
object created
using auto_ptr
object deleted!
--------------------
object created
using unique_ptr
object deleted!