zoukankan      html  css  js  c++  java
  • 【c++】动态内存

    静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。注意:const常量在定义时必须初始化

    栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放,栈区由系统自动分配。

    堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。

    shared_ptr类

    shared_ptr初始化:使用make_shared<T>(args)函数

    shared_ptr<int> p=make_shared<int>(42);

    auto p=make_shared<string>();

    每个shared_ptr都有一个关联的计数器(引用计数)即多少个指针指向shared_ptr管理的变量,无论何时我们拷贝一个shared_ptr,计数都会递增。当我们给shared_ptr赋予一个新值或是shared_ptr被销毁时,计数器就会递减。一旦一个shared_ptr的计数器变为0,就会自动释放自己管理的对象。

    auto p=make_ptr<int>(42);//p指向的对象只有一个引用者

    auto q(p);//p和q指向相同对象,此对象有两个引用者

    auto r=make_shared<int>(42);

    r=q;//r原来指向的对象已没有引用者,会自动释放

    总结:智能指针类能记录有多少shared_ptr指向相同的对象,并能在恰当的时候自动释放对象。

    直接管理内存

    动态分配的对象是默认初始化的,这意味着内置类型或组合类型的对象的值是未定义的,而类类型对象将用默认构造函数进行初始化

    string *ps=new string;//初始化为空string

    int *pi=new int;//pi指向一个未初始化的int

    传统的构造方式(圆括号):

    int *pi=new int(1024);

    我们传递给delete的指针必须指向动态分配的内存,或者是空指针,释放一块不是new分配的内存,或者将相同的指针释放多次,其行为是未定义的。

    shared_ptr与new结合使用

    我们不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式来初始化一个智能指针。

    shared_ptr<int>p = new int(1024);//错误
    shared_ptr<int>q(new int(1024));//正确

    class shared                                    //一个拥有shared_ptr的类  
    {
    private:
        shared_ptr<int> p;                          //shared_ptr成员变量  
    public:
        shared(shared_ptr<int> p_) :p(p_){}          //构造函数初始化shared_ptr      
        void print()                                //输出shared_ptr的引用计数和指向的值      
        {
            cout << "count:" << p.use_count()
                << "v =" << *p << endl;
        }
    };
    void print_func(shared_ptr<int> p)                //使用shared_ptr作为函数参数  
    {
        //同样输出shared_ptr的引用计数和指向的值      
        cout << "count:" << p.use_count()
            << " v=" << *p << endl;
    }
    int main()
    {
        shared_ptr<int> p(new int(100));
        shared s1(p), s2(p);                        //构造两个自定义类       
        s1.print();
        s2.print();
        *p = 20;                                    //修改shared_ptr所指的值      
        print_func(p);
        s1.print();
        system("pause");
    }
    /*输出为
    count:3v =100
    count:3v =100
    count:4 v=20
    count:3v =20
    */

    在声明了shared_ptr和两个shared实例后,指针被它们所共享,因此引用计数为3.printf_func函数内部拷贝了一个shared_ptr对象,因此引用计数再增加1,但当退出函数时拷贝自动析构,引用计数又恢复3。

  • 相关阅读:
    【配置属性】—Entity Framework 对应表字段的类型的设定配置方法
    EntityFrame Work 6 Code First 配置字段为varchar 类型
    Echarts xAxis boundaryGap
    JavaScript Array和string的转换
    SQL server :主键和外键
    SQL server :“增删改查” 之 “改”
    SQL server :“增删改查” 之 “删”
    SQL server :“增删改查” 之 “增”
    Oracle不能连接故障排除【TNS-12541:TNS:无监听程序】
    LNMP平台部署及应用
  • 原文地址:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/3860456.html
Copyright © 2011-2022 走看看