gpt4 book ai didi

c++ - 是否使用 new char[] 或 malloc 的结果来转换 float * is IN(严格的别名违规)?

转载 作者:IT老高 更新时间:2023-10-28 23:01:08 26 4
gpt4 key购买 nike

其中哪些代码有 UB(具体来说,违反了严格的别名规则)?

void a() {
std::vector<char> v(sizeof(float));
float *f = reinterpret_cast<float *>(v.data());
*f = 42;
}

void b() {
char *a = new char[sizeof(float)];
float *f = reinterpret_cast<float *>(a);
*f = 42;
}

void c() {
char *a = new char[sizeof(float)];
float *f = new(a) float;
*f = 42;
}

void d() {
char *a = (char*)malloc(sizeof(float));
float *f = reinterpret_cast<float *>(a);
*f = 42;
}

void e() {
char *a = (char*)operator new(sizeof(float));
float *f = reinterpret_cast<float *>(a);
*f = 42;
}

我问这个是因为 this问题。

我认为,d 没有 UB(否则 malloc 在 C++ 中将毫无用处)。因此,bce 也没有它似乎是合乎逻辑的。我在某个地方错了吗?也许 b 是 UB,但 c 不是?

最佳答案

序言:存储对象在C++中是不同的概念。 Storage 是指内存空间,objects 是具有生命周期的实体,可以在一 block 存储中创建和销毁。随着时间的推移,存储可以重新用于托管多个对象。所有对象都需要存储,但也可以有没有对象的存储。


c 是正确的。 Placement-new 是在存储 (C++14 [intro.object]/1) 中创建对象的有效方法之一,即使该存储中有预先存在的对象。旧对象被存储的重用隐式销毁,只要它们没有非平凡的析构函数([basic.life]/4),这是完全可以的。 new(a) float;创建 float 类型的对象和现有存储中的动态存储持续时间 ([expr.new]/1)。

de 在当前对象模型规则中由于省略而未定义:通过泛左值表达式访问内存的效果仅在该表达式引用对象时才定义;而不是当表达式引用不包含对象的存储时。 (注意:请不要对现有定义的明显不足留下非建设性的评论)。

这并不是说“malloc 没用”; malloc的效果|和 operator new是获取存储。然后您可以在存储中创建对象并使用这些对象。这实际上正是标准分配器和 new 的方式。表达,工作。

ab 是严格的别名违规:float 类型的泛左值用于访问不兼容类型的对象 char . ([basic.lval]/10)


There is a proposal这将使所有情况都得到很好的定义(除了下面提到的 a 的对齐方式):根据这个提议,使用 *f在该位置隐式创建该类型的对象,但有一些注意事项。


注意:在 be 的情况下没有对齐问题,因为 new-expression 和 ::operator new保证为任何类型([new.delete.single]/1)正确对齐分配存储。

但是,对于 std::vector<char> ,即使标准规定 ::operator new被调用以获得存储,标准不要求将第一个 vector 元素放置在该存储的第一个字节中;例如 vector 可以决定在前面分配 3 个额外的字节并将其用于一些簿记。

关于c++ - 是否使用 new char[] 或 malloc 的结果来转换 float * is IN(严格的别名违规)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46960774/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com