【C++】 为什么C++空类占一个字节

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dengjin20104042056/article/details/80300496

00. 目录

01. 测试程序和结果分析

测试程序如下:

#include <iostream>

using namespace std;

//声明一个空类
class A{

};

int main(void)
{

    //使用空类定义两个对象
    A a1;
    A a2;

    cout << "sizeof(a1): " << sizeof(a1) << endl;
    cout << "sizeof(a2): " << sizeof(a2) << endl;

    cout << "&a1: " << &a1 << endl;
    cout << "&a2: " << &a2 << endl;

    return 0;
}

编译和执行结果:
执行结果

结果分析:
1) 其实这是C++中空类占位问题
2) 在C++中空类会占一个字节,这是为了让对象的实例能够相互区别。具体来说,空类同样可以被实例化,并且每个实例在内存中都有独一无二的地址,因此,编译器会给空类隐含加上一个字节,这样空类实例化之后就会拥有独一无二的内存地址。如果没有这一个字节的占位,那么空类就无所谓实例化了,因为实例化的过程就是在内存中分配一块地址。

注意:当该空白类作为基类时,该类的大小就优化为0了,这就是所谓的空白基类最优化。

02. 单继承空白基类最优化问题

测试程序如下:

#include <iostream>

using namespace std;

//声明一个空类 基类
class A{

};

//公有继承
class B : public A
{
public:
    int a;
};

int main(void)
{

    //使用空类定义两个对象
    A a1;
    B b1;

    cout << "sizeof(a1): " << sizeof(a1) << endl;
    cout << "sizeof(b1): " << sizeof(b1) << endl;

    cout << "&a1: " << &a1 << endl;
    cout << "&b1: " << &b1 << endl;

    return 0;
}

编译和执行结果如下:
编译和执行结果

现象分析:
在上例中,大部分编译器对于sizeof(b1)的结果是4,而不是8。这就是所谓的空白基类最优化在(empty base optimization-EBO 或 empty base classopimization-EBCO)。在空基类被继承后由于没有任何数据成员,所以子类优化掉基类所占的1 byte。EBO并不是c++标准所规定必须的,但是大部分编译器都会这么做。由于空基类优化技术节省了对象不必要的空间,提高了运行效率,因此成为某些强大技术的基石,基于类型定义类如stl中的binary_function、unary_function、iterator、iterator_traits的实现复用;基于策略类如内存管理、多线程安全同步的实现复用。当某个类存在空类类型的数据成员时,也可考虑借助EBO优化对象布局.

注意:空白基类最优化无法被施加于多重继承上只适合单一继承

03. 多继承空白基类最优化问题

测试程序:

#include <iostream>

using namespace std;

//声明一个空类 基类
class A{

};

//声明另外一个空类 基类
class B{

};

//公有继承
class C : public A
{
public:
    int a;
};

class D : public A, public B
{
public:
    int a;
};

int main(void)
{

    //使用空类定义两个对象
    A a1;
    C c1;
    D d1;

    cout << "sizeof(a1): " << sizeof(a1) << endl;
    cout << "sizeof(c1): " << sizeof(c1) << endl;
    cout << "sizeof(d1): " << sizeof(d1) << endl;

    cout << "&a1: " << &a1 << endl;
    cout << "&c1: " << &c1 << endl;
    cout << "&d1: " << &d1 << endl;

    return 0;
}

编译和执行结果:

1) Linux 64系统执行的结果:
编译和执行结果

2) Vs2015执行的结果
编译和执行结果

现象分析
该现象随着编译器不同可能不一样

猜你喜欢

转载自blog.csdn.net/dengjin20104042056/article/details/80300496