C++中的内存

rqdpfwrv  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(118)

如果我有这样的代码,在C中是法律的:

int* i = static_cast<int*>(std::malloc(sizeof(int)));
*i = 123;

字符串
这也是法律的C++吗?或者它会调用未定义/实现定义的行为?对于什么类型它是法律的?
或者在这种情况下需要执行new(i) int (123);吗?
例如,对于非平凡类,它不可能是法律的,因为对象从未被构造,但随后它的operator=被调用。

tct7dpnv

tct7dpnv1#

这是法律的,因为C20。在此之前,它在技术上是非法的,但无论如何,在实践中工作。
这通常是UB,因为在生命周期开始之前访问对象,但C
20添加了[intro.object]/11
某些操作被描述为在指定的存储区域内 * 隐式创建对象 *。对于被指定为隐式创建对象的每个操作,该操作隐式创建并启动零个或多个隐式生存期类型的对象的生存期([basic.types.general])如果这样做将导致程序具有定义的行为,则在其指定的存储区域中。如果没有这样的对象集将给予程序定义的行为,程序的行为是未定义的。2如果多个这样的对象集将给予程序定义的行为,则不指定创建哪一个这样的对象集。

  • [注4:此类操作不会启动本身不是隐式生存期类型的此类对象的子对象的生存期。-结束注]* 

malloc()[c.malloc]/4中得到了祝福:
这些函数在返回的存储区域中隐式地创建对象([intro.object]),并返回一个指向合适的创建对象的指针。在calloc和realloc的情况下,对象分别在存储置零或复制之前创建。
(Note“返回一个指向合适的创建对象的指针”,否则需要std::launder()
这适用于“隐式生存期类型”:[basic.types.general]/9
标量类型、隐式生存期类类型([class.prop])、数组类型和这些类型的cv限定版本统称为隐式生存期类型。
[class.prop]/9
一个类S是一个隐生存期类,如果
(9.1)- 它是一个聚合,其析构函数不是用户提供的,或者
(9.2)- 它至少有一个平凡的合格构造函数和一个平凡的非删除析构函数。
(9.1)这听起来令人困惑,直到你读到“注4”在第一个报价在这个答案。

csga3l58

csga3l582#

从C++20开始,这一点就按照intro.object#11进行了很好的定义。该标准甚至有一个类似的例子,其中从std::malloc获得的指针被解引用。
从介绍对象:
[示例]

#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;
}

字符串
结束示例]

相关问题