引言

new 分配的内存块与常规变量声明分配的内存块不同,常规变量声明分配的内存在被称为栈的内存区域中,而new在被称为堆(也称自由存储区)的内存区域分配内存。
直接声明的对象,比如 BinNode a,即在栈上面的对象,所在作用域结束后,栈空,然后会自动执行析构函数,而new创建出来的是在堆上的对象,如果不调用delete,即使它所在的作用域已经结束,也不会调用析构函数。系统os 会在程序结束,回收该部分内存。
20190729134547599.png

简介

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!

参考文章

https://www.cnblogs.com/chenmingjun/p/8283374.html

最后修改:2020 年 12 月 10 日
如果觉得我的文章对你有用,请随意赞赏