gpt4 book ai didi

c++ - 放置 `new` 可以依赖底层存储值吗?

转载 作者:可可西里 更新时间:2023-11-01 17:36:45 25 4
gpt4 key购买 nike

让我们从一些上下文开始。

自定义内存池使用的代码类似于以下内容:

struct FastInitialization {};

template <typename T>
T* create() {
static FastInitialization const F = {};

void* ptr = malloc(sizeof(T));
memset(ptr, 0, sizeof(T));
new (ptr) T(F);
return reinterpret_cast<T*>(ptr);
}

想法是,当使用 FastInitialization 调用时,构造函数可以假设存储已经零初始化,因此只初始化那些需要不同值的成员。

GCC(至少是 6.2 和 6.3)不过有一个“有趣”的优化开始了。

struct Memset {
Memset(FastInitialization) { memset(this, 0, sizeof(Memset)); }

double mDouble;
unsigned mUnsigned;
};

Memset* make_memset() {
return create<Memset>();
}

编译为:

make_memset():
sub rsp, 8
mov edi, 16
call malloc
mov QWORD PTR [rax], 0
mov QWORD PTR [rax+8], 0
add rsp, 8
ret

但是:

struct DerivedMemset: Memset {
DerivedMemset(FastInitialization f): Memset(f) {}

double mOther;
double mYam;
};

DerivedMemset* make_derived_memset() {
return create<DerivedMemset>();
}

编译为:

make_derived_memset():
sub rsp, 8
mov edi, 32
call malloc
mov QWORD PTR [rax], 0
mov QWORD PTR [rax+8], 0
add rsp, 8
ret

也就是说,只有struct的前16个字节,也就是它的base对应的部分,被初始化了。调试信息确认对 memset(ptr, 0, sizeof(T)); 的调用已被完全省略。

另一方面,ICC 和 Clang 都在完整大小上调用了 memset,这是 Clang 的结果:

make_derived_memset():               # @make_derived_memset()
push rax
mov edi, 32
call malloc
xorps xmm0, xmm0
movups xmmword ptr [rax + 16], xmm0
movups xmmword ptr [rax], xmm0
pop rcx
ret

因此 GCC 和 Clang 的行为不同,问题就变成了:GCC 是正确的并且产生更好的汇编,还是 Clang 是正确的但 GCC 有问题?


或者,就语言律师而言:

在什么情况下构造函数可以依赖存储在其分配存储空间中的先前值?

注意:我认为这只与位置 new 相关,但我很高兴以其他方式显示。

最佳答案

May placement new rely on underlying storage value?

不,它可能不会。来自 [dcl.init]:

If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced (5.18).

不确定值意味着不确定。这并不意味着,在放置新表达式的情况下,必须保留以前的内存。允许编译器对内存做任何它想做的事情——包括但不限于什么都不做。

Under which circumstances may a constructor rely on the previous value stored in its allocated storage?

[dcl.init] 中的后续段落列出了在生成不确定值时行为不是未定义的情况,但它们只与无符号窄字符类型有关。

所以,在任何情况下都不能。

关于c++ - 放置 `new` 可以依赖底层存储值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41890635/

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