我被告知以下代码在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是非配偶的。
它被广泛认为是标准中的一个缺陷,但重要性很低,因为C++编译器围绕UB的特定部分所做的优化不会导致该用例出现问题。
至于第二个问题,C++并没有强制要求C++和C如何交互。所以所有与C的交互都是。。。UB,也就是C++标准未定义的行为。