Rumah  >  Soal Jawab  >  teks badan

c++ - 为什么析构函数什么也不写仍然会delete其成员指针?


class A{
public:
    int _a;
    A(int a) :_a(a){};
};
class B{
    A* _ap;
public:
    B(A& a){
        _ap = &a;
    }
    ~B(){
        //这里并不执行什么,但是_ap仍然被delete了。
    };
};
void main(){
    A* a = new A(1);
    B b(*a);
    delete &b;
    cout << a->_a;
}

是不是不管你析构函数写的什么,都一定会delete掉其所有的成员变量?

PHP中文网PHP中文网2714 hari yang lalu600

membalas semua(4)saya akan balas

  • 怪我咯

    怪我咯2017-04-17 13:32:21

    是不是不管你析构函数写的什么,都一定会delete掉其所有的成员变量?

    绝对不可能。

    另外,b不是new出来的,把它delete掉的结果是未定义的

    以上两种可以说都是fatal error!!!
    因为前者会导致内存泄漏
    后者会导致你的程序在某个神奇的时刻以一种神奇的方式crash掉,而且在crash掉之后你基本上很难发现其中隐含的奥秘

    balas
    0
  • 迷茫

    迷茫2017-04-17 13:32:21

    题主的程序中有几个问题:

    class A{
    public:
        int _a;  // 不推荐,变量名不要以下划线开始,但可以以下划线结束,比如 a_
        A(int a) :_a(a){};
    };
    class B{
        A* _ap;  // 同上
    public:
        B(A& a){
            _ap = &a;
        }
        ~B(){
            //这里并不执行什么,_ap 也没有在这里被 delete
        };
    };
    void main(){
        A* a = new A(1);
        B b(*a);
        delete &b;  // 错误,&b 并不是指向动态分配的内存的指针,对其进行 delete 是未定义的(见文末标准引用)
        cout << a->_a;
        delete a;  // 错误,a 是指向动态分配的内存的指针,需要进行 delete,而题主漏掉了
    }

    是不是不管你析构函数写的什么,都一定会delete掉其所有的成员变量?

    不是。你不写 delete 则析构函数就不会释放相应指针指向的内存。

    此外,题主的类B在设计上也存在问题。如果一个类的成员是一个指针,那么需要考虑:

    • B的成员_ap是指向栈中的对象还是动态内存中的对象?

      • 如果是指向栈中的对象,就不需要考虑内存的分配和释放问题;

      • 如果是指向动态内存中的对象,则需要考虑内存的分配和释放问题。

    • 如果指向动态内存,那么指向的内存该由谁管理(分配、释放)?是类B还是类B的用户(如main函数)?

      • 如果是由类B管理(这也是通常的做法),那么相应的构造函数和析构函数就会负责动态内存的分配和释放。也就是 C++ 中常说的 Resource Acquisition Is Initialization(RAII)。

      • 如果由类B的用户(如main函数)进行管理,那么用户(如main函数)就必须在实现的时候仔细考虑资源的分配和释放问题,否则很容易出错。

    最后,如果不是有特殊需求,不建议使用原始指针(raw pointer),而是使用 STL 里的智能指针shared_ptrweak_ptrunique_ptr,智能指针可以自动管理所指向的动态内存,所以不需要考虑什么时候该释放内存、会不会多次释放同一块内存、会不会一不小心就搞出个野指针等问题。使用方法可以参考 C++ Primer 5e Chapter 12 Dynamic Memory。

    C++ 11 Standard § 5.3.5/2
    … In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined. …

    balas
    0
  • PHP中文网

    PHP中文网2017-04-17 13:32:21

    只有动态内存需要自己手动释放,其余的变量在类变量销毁时自动释放。你这里没有动态内存的分配,所以什么都不用写

    balas
    0
  • 大家讲道理

    大家讲道理2017-04-17 13:32:21

    两件事情:
    1、成员变量如果是指针。那么程序需要分配的内存是存储指针占用的内存(32位程序是4个字节)和指针指向的内存。其中指针占用的内存是有编译器管理的,而指针指向的内存是你自己管理的。
    也就是,这个指针占用的内存(4个字节)就会自动在析构函数里自动释放。但是指针指向的部分内存默认析构函数是不会帮你释放的,因为编译器也不知道你这个指针指向的是不是你自己分配的内存,也不知道你将来还会不会用这段内存。
    2、当程序/进程执行完,程序占用的所有内存都会被操作系统释放。即使没有显示的delete

    balas
    0
  • Batalbalas