【发布时间】:2014-02-21 17:10:57
【问题描述】:
当我讨论我的另一个问题 (Member not zeroed, a clang++ bug?) 时,我实际上想到了这个问题。那个问题是关于 C++11 值初始化的,但是当我看到有人在那里发布的 C++03 值初始化规则时,我很困惑。
C++03 的值初始化规则是:
对 T 类型的对象进行值初始化意味着:
- 如果 T 是具有用户声明的构造函数 (12.1) 的类类型(第 9 条),则调用 T 的默认构造函数(并且 如果 T 没有可访问的默认值,则初始化格式错误 构造函数);
- 如果 T 是没有用户声明的构造函数的非联合类类型,则 T 的每个非静态数据成员和基类组件都是 值初始化;
- 如果T是数组类型,那么每个元素都是值初始化的;
- 否则,对象被零初始化
请查看第二个项目符号,它为没有用户声明的构造函数的类型定义值初始化过程。这条规则没有提到构造函数调用。从 value-initialize 其他情况的描述或者从 default-initialize 的描述中我们可以看出,如果要调用构造函数,会在标准的正文中明确提到。我知道构造函数不会被调用的某些初始化形式(例如,聚合的 {}-initialization),但 non-union class type without a user-declared constructor 的值初始化应该是这种情况吗?这种类型的隐式声明的构造函数很容易变得不平凡。例如:
class A {
public:
virtual void f() {}
};
根据C++03中的规则,如果在A的对象的值初始化过程中没有调用隐式声明的non-trivial构造函数,那么该对象的vptr如何获取设置? (我知道与 vptr 相关的东西都是由实现定义的,但这并没有改变我在这里试图提出的主要观点。)
(有人会争辩说,在规则中没有提及构造函数调用并不意味着构造函数不会被调用。好吧。假设构造函数将根据我可能忽略的其他规则被调用,但由于所有无论如何,成员都需要进行值初始化,这不会导致成员的构造函数被多次调用吗?)
当 C++03 到处都是 C++11 时问一个问题似乎毫无价值。是的,这是一个有效的观点。但是,如果我最终弄清楚这一点(无论我是否错以及为什么),我认为我或多或少可以学到一些东西。
编辑:也许我不应该以 vptr 为例。我的观点是,跳过对非平凡构造函数的调用不会对对象的有效性造成一些潜在的问题吗?毕竟,它被称为不平凡是有原因的。
【问题讨论】:
-
标准引用并不排除编译器在初始化期间插入自己的magic,而设置 vtable 就是其中的一部分。
-
@Praetorian:也许我不应该以 vptr 为例。我的观点是,跳过对非平凡构造函数的调用不会对对象的有效性造成一些潜在的问题吗?毕竟,它被称为不平凡是有原因的。
标签: c++ language-lawyer c++03