Aco*_*gua 15 c++ malloc object-lifetime language-lawyer
请考虑以下示例代码:
class C
{
public:
int* x;
};
void f()
{
C* c = static_cast<C*>(malloc(sizeof(C)));
c->x = nullptr; // <-- here
}
Run Code Online (Sandbox Code Playgroud)
如果由于任何原因我不得不忍受未初始化的内存(当然,如果可能的话,我会打电话new C()),我仍然可以调用放置构造函数.但是,如果我省略这一点,如上所述,并手动初始化每个成员变量,是否会导致未定义的行为?即绕过构造函数本身未定义的行为,或者用类外的一些等效代码替换调用它是否合法?
(通过另一个完全不同的问题遇到这个问题;要求好奇......)
Ami*_*rsh 10
事实上,C++ 20 之前的 C++ 规范措辞将对象定义为(例如 C++17 措辞,[intro.object]):
C++ 程序中的构造创建、销毁、引用、访问和操作对象。对象由定义 (6.1)、new 表达式 (8.5.2.4)、隐式更改联合的活动成员 (12.3) 或创建临时对象 (7.4, 15.2) 创建。
没有提到使用 malloc 分配创建对象的可能性。使其成为事实上的未定义行为。
然后它被视为一个问题,这个问题后来由https://wg21.link/P0593R6解决,并被接受为自 C++98 以来所有 C++ 版本的 DR,然后添加到 C++20 规范中,新的措辞:
- C++ 程序中的构造创建、销毁、引用、访问和操作对象。一个对象是由一个定义、一个新表达式、一个隐式创建对象的操作创建的(见下文) ......
...
- 此外,在指定的存储区域内隐式创建对象之后,一些操作被描述为生成指向合适的创建对象的指针。这些操作选择一个隐式创建的对象,其地址是存储区域的起始地址,并产生一个指向该对象的指针值,如果该值将导致程序具有定义的行为。如果没有这样的指针值会给程序定义的行为,则程序的行为是未定义的。如果多个这样的指针值会给程序定义的行为,则未指定产生哪个这样的指针值。
C++20 规范中给出的示例是:
#include <cstdlib>
struct X { int a, b; };
X *make_x() {
// The call to std?::?malloc implicitly creates an object of type X
// and its subobjects a and b, and returns a pointer to that X object
// (or an object that is pointer-interconvertible ([basic.compound]) with it),
// in order to give the subsequent class member access operations
// defined behavior.
X *p = (X*)std::malloc(sizeof(struct X));
p->a = 1;
p->b = 2;
return p;
}
Run Code Online (Sandbox Code Playgroud)
没有生物C,所以假装有一个会导致未定义的行为.
在委员会的奥卢会议上通过的P0137R1通过如下定义对象来明确这一点([intro.object]/1):
一个目的是通过一个定义创建([basic.def]),通过一个新的表达式([expr.new])中,当隐式地改变联合的活性件([class.union]),或者当一个临时对象创建([conv.rval],[class.temporary]).
reinterpret_cast<C*>(malloc(sizeof(C))) 不是这些.
另请参阅此std-proposal主题,其中一个非常类似的例子来自Richard Smith(修正了错字):
Run Code Online (Sandbox Code Playgroud)struct TrivialThing { int a, b, c; }; TrivialThing *p = reinterpret_cast<TrivialThing*>(malloc(sizeof(TrivialThing))); p->a = 0; // UB, no object of type TrivialThing here
[basic.life]/1引用仅在首先创建对象时适用.请注意,"简单"或"空白"(在CWG1751完成术语更改之后)初始化,因为该术语在[basic.life]/1中使用,是对象的属性,而不是类型,因此"有一个对象,因为它的初始化是空的/平凡的"是倒退的.
| 归档时间: |
|
| 查看次数: |
654 次 |
| 最近记录: |