• C++对象内存模型1(堆栈模型)


    对象内存模型

    一. 栈(Stack) VS. 堆(heap)

    • 栈 
      • 由系统自动管理,以执行函数为单位
      • 空间大小编译时确定(参数+局部变量)
      • 函数执行时,系统自动分配一个stack
      • 函数执行结束时,系统立即自动回收stack
    • 堆 
      • 在c++中由程序员手动控制
      • 手动分配new和malloc
      • 手动释放delete和free
      • 具有全局性,总体无大小限制
      • 容易造成内存泄露

    1. Myclass c(10); // 栈对象,空间大小在编译时确定,函数执行结束,系统立即回收

    2. 

    Myclass* func(){
        Myclass c(10);
        return &c; //返回栈内存地址,指针悬浮,极端错误! 
    }

    3.

    Myclass func(){
        Myclass c(10);
        Aclass a(100);     
        c.pa = &a;      //指向栈(local)对象,错! 
        return c;          
    } 

    结论: 指针指向栈对象,就要极度小心,一般会有问题!

    4

    Myclass* func(){
        Myclass *pa = new Myclass();
        return pa;   //小范围看没问题,但违背谁分配谁释放原则,此例接受者不知道要delete 
    }

    总结返回指针问题:

    返回栈指针: 完全错误

    返回堆指针:释放可能有问题 ,易造成内存泄露

    故一般不推荐

    5 堆对象内存模型

    6. 栈对象内存模型

    二. 变量模型与使用 (对象,指针,引用; 声明,传参,返回值)

    1. 声明与符号

    “*” : 声明时,指针

             用在指针前,解指针

    “&”: 声明时,引用

            用在对象前,取地址

    复制代码
    MyClass c;  //对象,一定在栈上
    
    MyClass* pc;    //指针,要问自己是栈指针,还是堆指针
    
    MyClass& c2 = c;    //引用,要问自己是栈引用,还是堆引用。本例为栈引用
    // 举例堆引用 Myclass *pc2 = new Myclass(); Myclass& c3 = *pc2; c3为堆引用
    c = *pc; //解指针, 可指向堆对象,也可以指向栈对象 //pc指向哪里,*pc即为指向哪里的对象(堆/栈) //又c在栈上 再调用拷贝构造函数完成 c = *pc pc = &c; //取地址
    复制代码

    2 传参分析

    复制代码
    //对象
    void func1(MyClass c) {    // 对象往往较大,开销大,一般不!
    }
    //指针
    void func2(MyClass* pc) { // 成本ok,但无法区分堆/栈,有delete问题
    }
    //引用
    void func3(MyClass& mc) { //推荐,不想双向传递用const
    }
    复制代码

    const& 为 pass by value好的替代品

    void func3(const MyClass& mc) {
    }

    调用方法:

    MyClass c1;
    func1(c1);  //调用拷贝构造
    func2(&c1); //不调用拷贝构造
    func3(c1);  //不调用拷贝构造,注意参数就写值即可,参考笔记2,传递者无需知道接受者的接受方式。乱加符号可能变成取地址了

    3. 返回值分析

    返回对象分析:

    MyClass func1() {
        MyClass c1;
        return c1;  //正确,调用拷贝构造
        MyClass* pc2 = new MyClass();
        return *pc2;  // 返回时调用拷贝构造,结束后pc2就取不到了,内存无法释放,一定存在内存泄露
    }

    返回指针分析:

    MyClass* func2() {
        MyClass c1;
        return &c1;   //极端错误,返回栈对象指针
        MyClass* pc2 = new MyClass();
        return pc2;   //不推荐,可能内存泄露,违背谁调用谁释放原则
    }

    故返回指针一般不推荐

    返回引用分析:

    MyClass& func3() {
        MyClass c1;
        return c1;   //  极端错误,栈对象结束就消亡了
        MyClass* pc2 = new MyClass();
        return *pc2;  //可能存在内存泄露,有办法取到pc2,但一般人不会去做,也不知道要做
    }

    返回传入参数的引用,ok且推荐,常见还有this指针

    MyClass& func4(MyClass& c) {
        return c;
    }
  • 相关阅读:
    23.2 编写笨的程序
    python面向对象
    面向对象封装
    python新式类删改查
    os模块sys模块 进度条实例
    选课系统练习程序
    python类相关
    xml模块
    json&pickle模块shelve模块
    Python写的ATM程序
  • 原文地址:https://www.cnblogs.com/yechanglv/p/6931000.html
Copyright © 2020-2023  润新知