菜鸟笔记
提升您的技术认知

c 空类编译器自动生成的6个成员函数-ag真人游戏

       在c 中,编译器会为空类提供哪些默认成员函数?分别有什么样的功能呢?

1、空类,声明时编译器不会生成任何成员函数

        对于空类,编译器不会生成任何的成员函数,只会生成1个字节的占位符。

        有时可能会以为编译器会为空类生成默认构造函数等,事实上是不会的,编译器只会在需要的时候生成6个成员函数:一个缺省的构造函数、一个拷贝构造函数、一个析构函数、一个赋值运算符、一对取址运算符和一个this指针。

 代码:

#include 
using namespace std;
class empty_one
{
};
class empty_two
{};
class empty_three
{
    virtual void fun() = 0;
};
class empty_four :  public empty_two, public empty_three
{
};
int main()
{
  cout<<"sizeof(empty_one):"<

运行结果:

分析:

类empty_one、empty_two是空类,但空类同样可以被实例化,而每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址,所以sizeof(empty_one)和sizeof(empty_two)的大小为1。

类empty_three里面因有一个纯虚函数,故有一个指向虚函数的指针(vptr),64位系统分配给指针的大小为8个字节,所以sizeof(empty_three)的大小为8。

类empty_four继承于empty_two和empty_three,编译器取消empty_two的占位符,保留一虚函数表,故大小为8。

2、空类,定义时会生成6个成员函数

        当空类empty_one定义一个对象时empty_one pt;sizeof(pt)仍是为1,但编译器会生成6个成员函数:一个缺省的构造函数、一个拷贝构造函数、一个析构函数、一个赋值运算符、两个取址运算符。

class empty
{};

等价于:

class empty
{
  public:
    empty();                            //缺省构造函数
    empty(const empty &rhs);            //拷贝构造函数
    ~empty();                           //析构函数 
    empty& operator=(const empty &rhs); //赋值运算符
    empty* operator&();                 //取址运算符
    const empty* operator&() const;     //取址运算符(const版本)
};

使用时的调用情况:

empty *e = new empty();    //缺省构造函数
delete e;                  //析构函数
empty e1;                  //缺省构造函数                               
empty e2(e1);              //拷贝构造函数
e2 = e1;                   //赋值运算符
empty *pe1 = &e1;          //取址运算符(非const)
const empty *pe2 = &e2;    //取址运算符(const)

c 编译器对这些函数的实现:

inline empty::empty()                          //缺省构造函数
{
}
inline empty::~empty()                         //析构函数
{
}
inline empty *empty::operator&()               //取址运算符(非const)
{
  return this; 
}           
inline const empty *empty::operator&() const    //取址运算符(const)
{
  return this;
}
inline empty::empty(const empty &rhs)           //拷贝构造函数
{
  //对类的非静态数据成员进行以"成员为单位"逐一拷贝构造
  //固定类型的对象拷贝构造是从源对象到目标对象的"逐位"拷贝
}
inline empty& empty::operator=(const empty &rhs) //赋值运算符
{
  //对类的非静态数据成员进行以"成员为单位"逐一赋值
  //固定类型的对象赋值是从源对象到目标对象的"逐位"赋值。
}

         例如:m是类c中的一个类型为t的非静态成员变量,若c没有声明拷贝构造函数(赋值运算符), m将会通过t的拷贝构造函数(赋值运算符)被拷贝构造(赋值);该规则递归应用到m的数据成员,直到找到一个拷贝构造函数(赋值运算符)或固定类型(例如:int、double、指针等)为止。

(1)上述运行结果依赖于编译器和64位、32位不同的系统。

(2)本博文只是总结一些c 特性,也有无法理解的地方,不足之处还请指出,在此先感谢!

网站地图