C++ 空基类优化
1. 继承体系中的内存模型
我们都知道,在C++中,不存在大小是零的类。即便是空类,也要占据一个字节,否则无法比较两个空类对象是否是同一个对象(在C/C++中,默认使用地址来判断两个变量是否是同一个)。
class BaseEmpty {
public:
BaseEmpty() { std::cout<<"Base address: "<< this << std::endl;}
};
int main(int argc, char const *argv[]) {
BaseEmpty empty_1{};
BaseEmpty empty_2{};
assert(&empty_1 != &empty_2); // 两个空类对象的地址肯定不同
std::cout<<sizeof(BaseEmpty{})<<std::endl; // 输出 1
}
Dervied_1继承了父类Base,Derived_1的内存模型等效于Derived_2
class Base {
public:
Base() = default;
private:
int num_{0};
bool state_{false};
};
class Derived_1 : public Base {
public:
Derived_1() = default;
private:
std::string name_{"CPP"};
};
class Derived_2 {
public:
Derived_2() = default;
private:
int num_{0};
bool state_{false};
// 子类的成员变量
std::string name_{"CPP"};
};
2. 空基类优化
对于空类BaseEmpty ,假设有另一个空类DerivedEmpty继承自BaseEmpty,空类DerivedDeeperEmpty继承自DerivedEmpty,那么DerivedDeeperEmpty对象的大小sizeof(DerivedDeeperEmpty{})会是几个字节???
class DerivedEmpty: public BaseEmpty {
public:
DerivedEmpty() {
std::cout<<"Derived address: "<< this << std::endl;
}
};
class DerivedDeeperEmpty: public DerivedEmpty {
public:
DerivedDeeperEmpty() {
std::cout<<"deeper address: "<< this << std::endl;
}
};
DerivedDeeperEmpty是个空类,也要占用两个字节,相当于内部分别包含了BaseEmpty、DerivedEmpty
class DerivedDeeperEmpty_eq {
public:
DerivedDeeperEmpty_eq() = default;
private:
BaseEmpty base_1_;
DerivedEmpty base_2_;
};
sizeof(DerivedDeeperEmpty_eq); // 2
DerivedDeeperEmpty明明只是个空类啊!!!大小却是2个字节???如果情况再极端点,DerivedDeeperEmpty还有更深的空子类,那么空子类的大小会不断膨胀???
在空类被用作基类时,如果不给它分配内存并不会导致它被存储到与同类型对象(包括子类对象)相同的地址上,那么就可以不给它分配内存。换句话说,BaseEmpty作为空基类时,下面两种情况,编译器不会为Basement对象在子类中分配内存:
-
子类单继承,比如类DerivedDeeperEmpty。
-

浙公网安备 33010602011771号