有人告诉我,在C++20之前,以下代码是未定义的行为:
int *p = (int*)malloc(sizeof(int));
*p = 10;
真的吗?
参数是在为int
对象赋值之前不会启动该对象的生存时间(P0593R6)。 要解决此问题,应使用位置new
:
int *p = (int*)malloc(sizeof(int));
new (p) int;
*p = 10;
我们真的必须调用默认构造函数来启动对象的生命时间吗?
同时,代码在纯C中并不是未定义的行为,但是如果我在C代码中分配int
并在C++中使用它会怎样呢?
// C source code:
int *alloc_int(void)
{
int *p = (int*)malloc(sizeof(int));
*p = 10;
return p;
}
// C++ source code:
extern "C" int *alloc_int(void);
auto p = alloc_int();
*p = 20;
还是未定义的行为吗?
真的吗?
是的。 从技术上讲,没有任何一部分:
int *p = (int*)malloc(sizeof(int));
实际上创建了一个int
类型的对象,因此取消引用p
是UB,因为那里没有实际的int
。
我们真的必须调用默认构造函数来启动对象的生命时间吗?
你必须按照C++对象模型来避免C++20之前的未定义行为吗? 是的。 任何编译器实际上会因为你不这样做而造成伤害吗? 据我所知没有。
[...] 还是未定义的行为吗?
是的。 在C++20之前,实际上还没有在任何地方创建int
对象,因此这就是UB。
是的,是UB。 枚举了int
可以存在的方式列表,没有一种方式适用于此,除非您认为malloc是aausal的。
它被广泛认为是标准中的一个缺陷,但重要性不高,因为C++编译器围绕UB的特定部分所做的优化并没有引起用例的问题。
至于第二个问题,C++并没有强制要求C++和C如何交互。 所以所有与C的交互都是。。。UB,也就是C++标准没有定义的行为。