如果普通默认构造函数不执行任何操作,为什么我们不能使用 malloc 创建平凡可构造的对象?

Why can we not create trivially constructible objects using malloc if the trivial default constructor performs no action?

本文关键字:创建 malloc 对象 不能 构造函数 默认 执行 任何 我们 为什么 操作      更新时间:2023-10-16

我很难理解以下引用自cppPreferences关于琐碎默认构造函数的段落。我已经搜索了堆栈溢出,但仍然没有得到明确的答案。所以请帮忙。

普通默认构造函数是不执行任何操作的构造函数。所有与 C 语言兼容的数据类型(POD 类型(都是默认构造的。但是,与 C 语言不同的是,具有微不足道的默认构造函数的对象不能通过简单地重新解释适当对齐的存储来创建,例如使用 std::malloc 分配的内存:placement-new 需要正式引入新对象并避免潜在的未定义行为。

具体来说,如果简单的默认构造函数什么都不做,为什么我们不能重新解释存储并假装有一个给定类型的对象?您能否提供一些示例来说明这将导致的潜在未定义行为

P0593R5 "为低级对象操作隐式创建对象"给出了这个例子:

struct X { int a, b; };
X *make_x() {
X *p = (X*)malloc(sizeof(struct X));
p->a = 1;
p->b = 2;
return p;
}

并解释:

使用 C++ 编译器编译时,此代码具有未定义的行为,因为p->a尝试写入X对象的int子对象,并且此程序从未创建过X对象或int子对象。

根据 [intro.object]p1 (C++17 Draft N4659(,

对象

由定义、新表达式、隐式更改联合的活动成员或创建临时对象时创建。

。而这个程序没有做这些事情。

在实践中,这是有效的,UB情况更多地被认为是标准的缺陷,而不是其他任何东西。 本文的全部目标是提出一种方法来解决这个问题和类似情况,而不会破坏其他事情。

出于"纯洁"的原因。

另一种选择和实际现状是,每个存储区域将同时包含适合该存储的所有对象。一些委员会成员对现状感到不安,很多人担心在同一位置(处于虚拟的、未初始化的状态(有无限多个物体的概念。

从来没有人能够证明在存储区域中拥有无限多个对象的逻辑问题。

因为他们有标准的不同部分说矛盾的事情,委员会成员只是决定认真对待标准中最糟糕的部分之一。

此外,如果您真的认真对待标准的这一部分,则严格不允许使用字符串文字。