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

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; 

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

这里是主要的汇编代码:

 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”的函数。

那么在我们调用一个空类的构造函数或赋值后,编译器的行为究竟是什么呢? 这本书是否会产生一些function? 如果是这样,他们在哪里存储?

function存在,但可以内联。

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

这本书所说的,在某种程度上是真实的,编译器创build的概念function,用于内联和直接调用。

但是生成的代码是空的,所以优化编译器会删除所有的函数的证据(设置这个指针),这些函数将不会被直接调用。

这本书并没有真正解释生成的代码,而是创build一个类的影响,以及它为正常操作产生的“隐藏”function。

这些方法的确是为这个类生成的,但它们是以“内联”方式生成的。

因为他们是逐成员的实现(例如,复制构造函数将复制构造所有成员),当class是空的时候,实际上没有任何事情在做,他们是内联,他们只是看不见的。

然而,记住这些方法自动执行…例如代码非常重要

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

是越野车,因为复制构造函数和赋值的自动生成的代码是错误的,将导致缓冲区的多个删除。

这不是因为已经写好的东西,而是因为没有写出来的东西,这是棘手的。 这就是为什么记住C ++会自动为你写什么是非常重要的:如果这个实现是你想要的那么完美,但是如果没有,那么通过提供正确的实现来修复它,或者禁止创build或使用那个错误的代码。

你和这本书是从不同抽象层次上来的。

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

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

因此,这本书当然不是不正确的,尽pipe为了清楚起见,我可能会使用不同的词。 坚持标准术语从不伤害。

Interesting Posts