是java把人给养废了还是c++的坑太多?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class A {
public:
string str;
A(const string &s):str(s){}
~A() {
cout << "destruct A\n";
}
};
class Base {
};
class B: public Base{
public:
A a;
vector<int> vec;
B(const vector<int> &v, A &a1):vec(v), a(a1){}
};
int main() {
//A *a = new A("hello");
//delete a;
vector<int> vec(100,5);
A a("aaa");
Base *b = new B(vec,a);
delete b;
return 0;
}
上面的程序有问题吗?
很严重的内存泄露。
C++的多态是通过虚函数实现的,要是不把Base的析构函数设为virtual的,在delete时,就调用base的析构函数了,而不是调用B的析构,然后B中有成员变量vec就没法释放了。
解决办法很简单,就是在base中添加个virtual的析构函数就行了。
先回忆下类的构造顺序,先构造基类,再构造派生类
具体的讲就是在构造类的时候,先构造基类,在构造当前类的成员变量,最后调用当前类的构造函数
析构的时候顺序相反
看上面的程序,delete b的时候,因为Base没有virtual的析构函数,所以,只会调用Base的析构函数,而不会调用B的析构函数,因为B的成员变量是在调用B的析构函数只会再析构的,所以,B的成员变量也不会被析构
刚开始看B类,是两个非指针类型的成员变量,所以,即使没有调用B类的默认生成的析构函数,只调用Base类的析构函数,应该也不会有内存泄露。但是,要注意的是,string和vector内部实现都只是一个指针,然后向堆中申请内存,如果不调用默认生成的析构函数,那么也不会析构string和vector,造成内存泄露。
解决方案:如果有继承的话,基类一定要有虚析构函数