C++03 中的某些值初始化情况不调用构造函数?
Certain case of value-initialization in C++03 doesn't call constructor?
实际上,我是在讨论我的另一个问题时想到这个问题的(成员未归零,一个clang++错误?)。这个问题是关于C++11值初始化的,但当我看到有人在那里发布的C++03值初始化规则时,我很困惑。
C++03中的值初始化规则是:
值初始化T类型的对象意味着:
- 如果T是一个具有用户声明构造函数(12.1)的类类型(子句9),则调用T的默认构造函数(并且如果T没有可访问的默认值,则初始化格式不正确构造函数)
- 如果T是没有用户声明构造函数的非并集类类型,则T的每个非静态数据成员和基类组件都是值已初始化
- 如果T是数组类型,则每个元素都被值初始化
- 否则,对象初始化为零
请看第二个项目符号,它为没有用户声明构造函数的类型定义了值初始化过程。这个规则没有提到构造函数调用。正如我们从值初始化的其他情况的描述或默认初始化的描述中看到的那样,如果应该调用构造函数,它将在标准的文本中明确提及。我知道有某种初始化形式的构造函数不会被调用(例如聚合的{}-初始化),但non-union class type without a user-declared constructor
的值初始化应该是这种情况吗?这种类型的隐式声明构造函数可以很容易地实现。例如:
class A {
public:
virtual void f() {}
};
根据C++03中的规则,如果在A
对象的值初始化过程中没有调用隐式声明的非平凡构造函数,那么该对象的vptr是如何设置的?(我知道与vptr相关的东西都是由实现定义的,但这并没有改变我在这里试图表达的主要观点。)
(有人会说,规则中没有提到构造函数调用并不意味着构造函数不会被调用。好吧。假设构造函数会根据我可能忽略的其他规则被调用,但由于所有成员都需要进行值初始化,这不会导致成员的构造函数被调用不止一次吗?)
当C++03已经是C++11的时候,问一个问题可能看起来毫无价值。是的,这是一个有效的观点。然而,我认为如果我最终弄清楚这一点(我是否错了,为什么错了),我或多或少可以学到一些东西。
编辑:也许我不应该用vptr作为例子。我的观点是,跳过对非平凡构造函数的调用不会对对象的有效性造成一些潜在的问题吗?毕竟,它被称为非琐碎是有原因的。
就标准而言,构造函数不负责设置vtable。设立vtable没有任何责任;就标准而言,vtables并不存在。
相反,vtable是编译器必须遵循的其他规则的结果,这些规则与虚拟函数绑定等有关。因此,无论是否调用构造函数,vtable都将在的某个地方设置,因为否则编译器将难以履行其其他义务。这与值初始化规则并不矛盾;相反,它为实施该规则的实际操作增加了细微差别。
当类X
没有用户提供的构造函数时,其默认构造函数的作用与X::X() {}
形式的构造函数(C++03[class.ctor]§6
)完全相同。就标准而言,这被定义为执行所有成员和基类子对象的默认初始化,,而不是其他因此,"调用生成的默认构造函数"与"默认初始化所有数据成员和基类子对象"相同
所以这实际上比你引用的值初始化做得"少"——因为值初始化值初始化所有数据成员和基类子对象。所以它完成了构造函数所做的一切,甚至更多。
就特定于实现的东西(如vtable指针)而言,这些都超出了标准的范围。编译器有责任确保其所有特定于实现的机制都能工作,而不考虑标准强制的构造函数调用。
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 在这种情况下,java对象是否可以调用本机函数
- 如果 std::vector::clear() 不是静态的,如何在没有实例的情况下调用它?
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- Doxygen - 如何在不生成图形的情况下生成文本调用关系结果
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- C++:带有大括号初始化列表的函数调用表达式 - 标准是否规定在单个元素列表的微不足道的情况下忽略大括号?
- 如果结构中的字符串比使用的 p/调用签名长或短,会发生什么情况?
- C++ - 如何在不调用其属性的情况下调用类?
- 有没有办法在没有虚拟的情况下使用基类指针调用派生类函数
- 为什么在这种情况下不调用我的虚拟函数实现?
- 在这种情况下,工会成员会调用自己的析构函数吗
- 如何在不迭代的情况下对数组中的每个元素调用方法
- C++-在没有自定义.lib文件的情况下从Lua C模块调用Lua函数
- 如何在派生类中不显式调用base::func()的情况下从基类执行虚拟函数
- C++ 在不释放内存的情况下调用析构函数
- Python在不引用类名的情况下调用类函数
- C++11 - 获取编译时的所有类变量,并在没有 Boost 的情况下为它们调用方法
- C ++:如何在不创建对象的情况下在主函数中调用方法
- 为什么在这种情况下调用非常量右值移动构造函数?