万古教员有名言,自信人生二百年。
个人主页:oioihoii 喜欢内容的话欢迎关注、点赞、收藏!感谢支持,祝大家祉猷并茂,顺遂无虞!

空类介绍
在C++中,一个不包含任何数据成员、成员函数(包括虚函数)和基类的类被称为空类。尽管空类看起来没有任何用途,但在某些情况下,它们可以作为一种类型安全的标记或标识符使用。以下是C++空类的一些特点:
- 占用空间:在C++中,空类并不是真正的“空”。即使一个类没有定义任何数据成员或成员函数,编译器也会为其分配一定的内存空间(通常是1字节),以确保每个对象都有一个独一无二的内存地址。这是因为在C++中,两个对象不能拥有相同的内存地址。
class MyClass {};
std::cout << sizeof(MyClass);  // 输出:1- 默认成员函数:C++编译器会为每个类(包括空类)自动生成六个默认成员函数:默认构造函数、析构函数、拷贝构造函数、拷贝赋值运算符、移动构造函数和移动赋值运算符。如果需要,这些函数可以被显式地声明和定义。
- 继承:空类可以作为基类被其他类继承。当一个类继承自空类时,编译器不会为基类分配任何内存空间。然而,如果一个类有多个空基类,编译器可能会为每个空基类分配一定的内存空间,以确保它们有不同的内存地址。
- 类型安全的标记:空类可以作为一种类型安全的标记或标识符使用。例如,我们可以定义一个空类,然后使用它来创建一个特殊的函数重载,这个重载只有在给定一个空类对象时才会被调用。
C++中空类的6个默认函数
- 默认构造函数:当一个对象被创建但没有被赋予初始值时,会调用默认构造函数。
class MyClass {
public:
    MyClass() {}  // 默认构造函数
};- 析构函数:当一个对象不再被使用时,会调用析构函数来清理和回收资源。
class MyClass {
public:
    ~MyClass() {}  // 析构函数
};- 拷贝构造函数:当一个对象以另一个对象为模板创建时,会调用拷贝构造函数。
class MyClass {
public:
    MyClass(const MyClass& other) {}  // 拷贝构造函数
};- 拷贝赋值运算符:当一个对象需要复制另一个对象的值时,会调用拷贝赋值运算符。
class MyClass {
public:
    MyClass& operator=(const MyClass& other) {}  // 拷贝赋值运算符
};- const成员函数&&取地址操作符重载:这是一个特殊的成员函数,它允许我们在const对象上调用它。
class MyClass {
public:
    MyClass* operator&() const {}  // const成员函数&&取地址操作符重载
};- const取地址操作符重载:这是一个特殊的成员函数,它允许我们在const对象上调用它。
class MyClass {
public:
    const MyClass* operator&() const {}  // const取地址操作符重载
};C++空类的6个构造函数
在C++的世界里,类(Class)是构建复杂系统的基石。它们封装了数据和操作数据的方法,形成了一种强大的抽象机制。当我们创建一个类时,C++编译器默默地为我们提供了六个默认的成员函数,它们是类的生命线,负责对象的创建、复制、移动和销毁。这六个成员函数分别是:
- 默认构造函数
- 拷贝构造函数
- 拷贝赋值运算符
- 移动构造函数
- 移动赋值运算符
- 析构函数
默认构造函数(一定存在)
默认构造函数是类的初始火花,它引发了对象的诞生。当我们没有为类定义任何构造函数时,C++会提供一个默认的构造函数,它不接受任何参数,也不执行任何操作。但是,它的存在确保了我们可以创建类的对象。
class MyClass {
    // 默认构造函数
    MyClass() = default;
};拷贝构造函数(一定存在)
拷贝构造函数是类的克隆机器,它创建了一个新的对象,作为已存在对象的副本。当我们需要复制一个对象时,拷贝构造函数就会被调用。如果我们没有定义拷贝构造函数,C++会提供一个默认的拷贝构造函数,它会逐个复制对象的所有成员。
class MyClass {
    // 拷贝构造函数
    MyClass(const MyClass& other) = default;
};拷贝赋值运算符(一定存在)
拷贝赋值运算符是类的传递者,它将一个对象的状态赋给另一个已存在的对象。当我们需要将一个对象的值赋给另一个对象时,拷贝赋值运算符就会被调用。如果我们没有定义拷贝赋值运算符,C++会提供一个默认的拷贝赋值运算符,它会逐个复制对象的所有成员。
class MyClass {
    // 拷贝赋值运算符
    MyClass& operator=(const MyClass& other) = default;
};移动构造函数、移动赋值运算符(不一定存在)
移动构造函数和移动赋值运算符是类的迁移者,它们将一个对象的资源“窃取”给另一个对象,而不是复制它们。这两个函数在处理大量数据或者资源时非常有用,因为它们可以避免不必要的复制操作,提高程序的效率。如果我们没有定义这两个函数,C++会提供默认的版本。
class MyClass {
    // 移动构造函数
    MyClass(MyClass&& other) = default;
    // 移动赋值运算符
    MyClass& operator=(MyClass&& other) = default;
};析构函数(一定存在)
析构函数是类的收割者,它在一个对象的生命周期结束时被调用,负责清理对象占用的资源。如果我们没有定义析构函数,C++会提供一个默认的析构函数,它不执行任何操作,但是它的存在确保了对象可以被正确地销毁。
class MyClass {
    // 析构函数
    ~MyClass() = default;
};注意事项
- 默认构造函数:如果你为类定义了其他构造函数(例如参数化构造函数或拷贝构造函数),C++将不再自动提供默认构造函数。如果你仍然需要一个默认构造函数,你必须手动定义它。
- 拷贝构造函数和拷贝赋值运算符:如果你的类包含指针成员,并且你希望进行深拷贝(即复制指针指向的数据,而不仅仅是指针本身),你需要手动定义拷贝构造函数和拷贝赋值运算符。否则,C++提供的默认版本将只进行浅拷贝,可能导致诸如数据共享和悬挂指针等问题。
- 析构函数:如果你的类分配了动态内存(例如,在构造函数或赋值运算符中使用了new),你需要在析构函数中使用delete来释放这些内存,以防止内存泄漏。
- 参数化构造函数:如果你为类定义了参数化构造函数,C++将不再自动提供默认构造函数。如果你仍然需要一个默认构造函数,你必须手动定义它。
- 转换构造函数:虽然转换构造函数可以方便地在不同类型之间进行转换,但它可能会导致意想不到的类型转换。因此,除非必要,否则最好避免定义能接受单个参数的转换构造函数,或者将其声明为explicit,以防止隐式类型转换。
- 规则的三/五:如果你为类定义了以下任何一个函数:析构函数、拷贝构造函数、拷贝赋值运算符、移动构造函数或移动赋值运算符,那么你应该考虑为类定义所有五个。这是因为,如果你需要自定义其中任何一个函数的行为,那么你可能也需要自定义其他函数的行为。这个规则可以帮助你避免一些常见的错误。
- 避免使用裸指针:如果可能,尽量避免在类中使用裸指针,因为它们很容易导致内存泄漏和其他问题。相反,你应该考虑使用智能指针,如std::unique_ptr或std::shared_ptr,它们可以自动管理内存,使你的代码更安全、更易于管理。
总结
C++中空类的6个默认函数和6个构造函数中析构函数、构造函数、拷贝构造函数、拷贝赋值运算符是一定存在的,移动构造函数、移动赋值运算符是否存在由代码实现决定。
 
 
                     
            
        













 
                    

 
                 
                    