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为了清楚起见,我可能会使用不同的词。 坚持标准术语从不伤害。