服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++空类的那点事儿

C++空类的那点事儿

2023-12-05 14:11思想觉悟 C/C++

在C++标准库中,五种迭代器类别都有对应的空类。这些空类用于标识迭代器的类别,并通过模板特化来实现对不同类型迭代器的特殊处理。

C++空类的那点事儿

什么是C++的空类

顾名思义,空类就是指哪些不包含成员变量的类。例如以下这个就是一个空类:

class EmptyBase {

};

既然如此,那么是不是说空类的内部一定不会其他代码呢?不是的,空类内部也可以包含其他东西,例如:构造函数、析构函数、静态成员变量、静态函数、成员函数、typedef语句等。

例如在以下代码中EmptyBase依然是空类:

class EmptyBase {
public:

    // 构造函数
    EmptyBase(){

    }
    // 析构函数
    ~EmptyBase(){

    }
    // typedef并没有给类增加成员或者函数

    typedef int INT_NUM;
    
    // 不涉及到内部成员变量的内部函数
    void set(int a){

    }
    // 静态函数
    static void setStr(const std::string& s){

    }

    // 静态变量
    static std::string str;
};

在C++11之后我们可以使用std::is_empty判断一个类是否是空类:

#include 
class EmptyBase {

};

int main() {
    
    auto aa = std::is_empty::value;
    std::cout << "是否是空类:" << aa << std::endl;
    return 0;
}

C++空类的大小

有以下计算空类大小的代码,你认为输出结果是多少?

#include 
class EmptyClass {
    // 空类
};
int main(int argc, char* argv[]) {
    std::cout << "sizeof(EmptyClass): " << sizeof(EmptyClass) << std::endl;
    return 0;
}

即使是空类,其大小也不会为0。在许多平台上,空类的大小为1;而在某些对于对齐(alignment)要求更严格系统上,空类的大小可能是另一个数(通常是4)。

为什么C++空类的大小不是0呢?

C++的设计者们不允许类的大小为0,因为每个对象都必须具有唯一的地址,特别是在涉及到取址和指针计算时,如果一个类的大小是0,那么指针的一切将会失效。 试想一下如果空类的大小为0,那么由空类它们构成的数组,其大小必然也是0,这会导致指针运算中普遍使用的性质失效。

空基类优化

C++标准规定,当空类作为基类时,只要不会与同一类型的另一个对象或子对象分配在同一地址,就不需为其分配任何空间。

#include 
class EmptyBase {
    // 空基类
};

class EmptyOne: public EmptyBase{
    // 空类1
};

class EmptyTwo: public EmptyOne{
    // 空类2
};

int main(int argc, char* argv[]) {
    std::cout << "sizeof(EmptyBase): " << sizeof(EmptyBase) << std::endl;
    std::cout << "sizeof(EmptyOne): " << sizeof(EmptyOne) << std::endl;
    std::cout << "sizeof(EmptyTwo): " << sizeof(EmptyTwo) << std::endl;
    return 0;
}

如果编译器支持空基类优化,上述程序所有的输出结果相同(一般是1),但均不为0。

我们修改一下代码,将EmptyTwo改为多继承,那么EmptyTwo还是空类吗?

class EmptyTwo: public EmptyOne,public EmptyBase{

};

答案是在多继承状态的EmptyTwo已经不是空类了, 虽然EmptyTwo和它的基类都没有任何成员。不过,EmptyTwo的基类EmptyOne和EmptyBase不能分配到同一地址空间, 否则EmptyTwo的基类EmptyBase会和EmptyOne的基类EmptyBase撞在同一地址空间上。换句话说,两个相同类型的子对象偏移量相同,这是C++对象布局规则不允许的。

对空基类优化进行限制的根本原因在于,我们需要能比较两个指针是否指向同一对象。 由于指针几乎总是用地址作内部表示,所以我们必须保证两个不同的地址(即两个不同的指针值)对应两个不同的对象。 虽然这种约束看起来并不非常重要,但是在实际应用中的许多类都是继承自一组定义公共typedefs的基类,当这些类作为子对象出现在同一对象中时,问题就凸现出来了,此时优化应被禁止。

空类存在的意义是什么

尽管在面向对象编程中,空类看起来可能有些多余,但是它们存确有它们的用途。

空类是一种有着潜在应用价值的编程技巧,例如空类可以被用于多种编程模式和设计模式中,它还可以作为数据类型的标记,用于在编译时实现条件编译。 空类也可以作为接口占位符,用于后续的继承实现或者后续扩展等。空类也在模板编程和元编程等高级编程技术中也发挥重要作用。

例如在C++标准库中,五种迭代器类别都有对应的空类。这些空类用于标识迭代器的类别,并通过模板特化来实现对不同类型迭代器的特殊处理,如图:

C++空类的那点事儿

原文地址:https://mp.weixin.qq.com/s?__biz=MzI2MDkzMTExMQ==&mid=2247485325&idx=1&sn=f1261a751961931c41e6ddefadb4c9c2

延伸 · 阅读

精彩推荐
  • C/C++c++连续输入未知个数的数字操作

    c++连续输入未知个数的数字操作

    这篇文章主要介绍了c++连续输入未知个数的数字操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    沧海一笑xhp4922021-10-11
  • C/C++使用OpenGL绘制Bezier曲线

    使用OpenGL绘制Bezier曲线

    这篇文章主要为大家详细介绍了使用OpenGL绘制Bezier曲线的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    dreamcs4472021-09-01
  • C/C++mac 配置Clion运行C和C++的环境的详细步骤

    mac 配置Clion运行C和C++的环境的详细步骤

    这篇文章主要介绍了mac 配置Clion运行C和C++的环境的步骤详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以...

    JunDream12122021-11-03
  • C/C++全排列算法的原理和实现代码

    全排列算法的原理和实现代码

    这篇文章主要介绍了全排列算法的原理和实现代码,全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个,需要的朋友可以参考下...

    C语言程序设计4202021-01-30
  • C/C++C语言简单实现求n阶勒让德多项式的方法

    C语言简单实现求n阶勒让德多项式的方法

    这篇文章主要介绍了C语言简单实现求n阶勒让德多项式的方法,涉及C语言复杂浮点数运算的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    keyunq7282021-04-04
  • C/C++从C语言过渡到C++之const

    从C语言过渡到C++之const

    C++中最早引入const是为了替代#define,后来又衍生出了其它用法。这一篇中我们来详细介绍const的各种常见用法。希望对大家学习C++有所帮助。...

    天花板5302021-05-26
  • C/C++C++ DLL动态库的创建与调用(类库,隐式调用)

    C++ DLL动态库的创建与调用(类库,隐式调用)

    本文主要介绍了C++ DLL动态库的创建与调用(类库,隐式调用),文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    廷益--飞鸟6642022-12-06
  • C/C++C++超详细讲解模板的使用

    C++超详细讲解模板的使用

    这篇文章主要介绍了C++中模板(Template)的详解及其作用介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参...

    努力变好的zz17952022-12-26