C++在一个空class中写调用什么函数?

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

Effective C++一书中,我看到了下面这段话:

As a result, if you write

class Empty{};

it's essentially the same as if you'd written this:

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

The following code will cause each function to be generated:

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    [=14=]x0,%eax
  4006d6:       5d                      pop    %rbp
  4006d7:       c3                      retq 

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

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

函数存在,但可以内联。

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

这本书说的在一定程度上是正确的,概念函数是由编译器创建的,用于内联和直接调用。

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

本书并没有真正试图解释生成的代码,而是解释创建 class 的影响,以及它为正常运行生成的 "hidden" 函数。

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

因为它们是逐个成员的实现(例如,复制构造函数将复制构造所有成员)当 class 为空时,它们实际上什么也没做,并且内联它们是只是看不见。

重要的是要记住这些方法会自动获得一个实现...例如代码

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

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

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

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

本书使用术语 "generated" 来指代编译器隐式定义到抽象 C++ 程序中的 C++ 函数。这绝对会发生。

您将其解释为在翻译程序中实际生成实际机器代码。这不是它的意思。只要保持原始抽象程序的语义,实际机器代码的生成总是受制于编译器的突发奇想。

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