c++在空类中编写和调用什么函数?

What function does C++ write and call in an empty class?

本文关键字:调用 什么 函数 c++      更新时间:2023-10-16

Effective c++ 这本书中,我看到了下面的段落:

因此,如果您写入
class Empty{};

本质上和你这样写是一样的:

class Empty {
public:
    Empty() { ... }
    Empty(const Empty& rhs) { ... }
    ~Empty() { ... }
    Empty& operator=(const Empty& rhs) { ... } // copy assignment operator
};

以下代码将生成每个函数:

Empty e1;
Empty e2(e1);
e2 = e1;

但是在反汇编了通过编译上面的代码创建的可执行文件之后,我意识到情况并非如此:没有调用任何函数。

下面是主要的汇编代码:
00000000004006cd <main>:
  4006cd:       55                      push   %rbp
  4006ce:       48 89 e5                mov    %rsp,%rbp
  4006d1:       b8 00 00 00 00          mov    $0x0,%eax
  4006d6:       5d                      pop    %rbp
  4006d7:       c3                      retq 

.text段中没有名为"Empty"的函数

那么在调用空类的构造函数或赋值之后,编译器的行为究竟是什么?它能像书上说的那样产生一些函数吗?如果有,它们存储在哪里?

函数存在,但可以内联。

当编译器内联函数时,它意识到它们是无操作的,并且没有生成代码。

书上所说的在某种程度上是正确的,名义函数是由编译器创建的,用于内联和直接调用。

但是生成的代码是空的,因此优化编译器将删除函数的任何证据(设置一个this指针),并且函数永远不会被直接调用。

这本书并不是真正试图解释生成的代码,而是创建类的影响,以及它为正常操作生成的"隐藏"函数。

这些方法确实是为类生成的,但它们是以"inline"方式生成的。

由于它们是逐成员实现(例如,复制构造函数将复制构造所有成员),当class为空时,它们实际上没有做任何事情,并且是内联的,它们只是不可见的。

记住这些方法是自动实现的,这一点非常重要。例如代码

struct Foo {
    char *buf;
    Foo() : buf(new char[10]) {}
    ~Foo() { delete[] buf; }
};

有bug,因为自动生成的复制构造函数和赋值代码是错误的,会导致多次删除缓冲区。

有bug不是因为写了什么东西,而是因为写了而不是,这很棘手。这就是为什么记住c++会自动为你编写的东西是极其重要的:如果实现是你想要的,那么它是完美的,但如果不是,那么通过提供正确的实现来修复它,或者禁止创建或使用错误的代码。

你和这本书是从不同的抽象层次来处理这种情况的。

书中使用术语"生成"来指编译器隐式地将c++函数定义为抽象的c++程序。这绝对会发生。

你把它解释为在翻译的程序中实际生成的实际机器代码。不是这个意思。只要保持原始抽象程序的语义,实际机器代码的生成总是受编译器的影响。

因此,这本书当然不是不正确的,尽管为了清楚起见,我可能会使用不同的词。使用标准术语永远不会有坏处。