数组放置新需要缓冲区中未指定的开销?
5.3.4 [expr.new]
给出了例子:
5.3.4 [expr.new]
of the C++11 Feb draft gives the example:
new(2,f) T[5]
导致调用 operator new[](sizeof(T)*5+y,2,f)
.
这里,x 和 y 是表示数组分配开销的非负未指定值;new-expression 的结果将从 operator new[]
返回的值偏移这个量.这种开销可以应用于所有数组new-expressions,包括那些引用库函数operator new[](std::size_t, void*)
和其他放置分配函数的数组.开销的数量可能因 new 的一次调用而异.――结束示例 ]
Here, x and y are non-negative unspecified values representing array allocation overhead; the result of the new-expression will be offset by this amount from the value returned by operator new[]
. This overhead may be applied in all array new-expressions, including those referencing the library function operator new[](std::size_t, void*)
and other placement allocation functions. The amount of overhead may vary from one invocation of new to another. ―end example ]
现在使用以下示例代码:
Now take the following example code:
void* buffer = malloc(sizeof(std::string) * 10);
std::string* p = ::new (buffer) std::string[10];
根据上面的引用,第二行 new (buffer) std::string[10]
会在内部调用 operator new[](sizeof(std::string) * 10+ y, buffer)
(在构造单独的 std::string
对象之前).问题是如果 y >0
,预分配的缓冲区会太小!
According to the above quote, the second line new (buffer) std::string[10]
will internally call operator new[](sizeof(std::string) * 10 + y, buffer)
(before constructing the individual std::string
objects). The problem is that if y > 0
, the pre-allocated buffer will be too small!
那么我怎么知道在使用 arrayplacement-new 时要预分配多少内存?
So how do I know how much memory to pre-allocate when using array placement-new?
void* buffer = malloc(sizeof(std::string) * 10 + how_much_additional_space);
std::string* p = ::new (buffer) std::string[10];
或者在这种情况下,标准是否保证 y == 0
?引用再次说:
Or does the standard somewhere guarantee that y == 0
in this case? Again, the quote says:
这个开销可以应用于所有数组new-expressions,包括那些引用库函数operator new[](std::size_t, void*)
和其他展示位置分配函数.
This overhead may be applied in all array new-expressions, including those referencing the library function
operator new[](std::size_t, void*)
and other placement allocation functions.
推荐答案
更新
Nicol Bolas 在下面的评论中正确地指出,这已经得到修复,operator new[](std::size_t, void* p)
的开销始终为零.
Update
Nicol Bolas correctly points out in the comments below that this has been fixed such that the overhead is always zero for operator new[](std::size_t, void* p)
.
此修复是作为缺陷报告完成的 于 2019 年 11 月,这使其可追溯至所有版本的 C++.
This fix was done as a defect report in November 2019, which makes it retroactive to all versions of C++.
不要使用 operator new[](std::size_t, void* p)
除非你事先知道这个问题的答案.答案是一个实现细节,可以随着编译器/平台而改变.尽管它对于任何给定平台通常都是稳定的.例如.这是 Itanium ABI 指定的内容.
Don't use operator new[](std::size_t, void* p)
unless you know a-priori the answer to this question. The answer is an implementation detail and can change with compiler/platform. Though it is typically stable for any given platform. E.g. this is something specified by the Itanium ABI.
如果您不知道这个问题的答案,请编写您自己的新的放置数组,以便在运行时进行检查:
If you don't know the answer to this question, write your own placement array new that can check this at run time:
inline
void*
operator new[](std::size_t n, void* p, std::size_t limit)
{
if (n <= limit)
std::cout << "life is good
";
else
throw std::bad_alloc();
return p;
}
int main()
{
alignas(std::string) char buffer[100];
std::string* p = new(buffer, sizeof(buffer)) std::string[3];
}
通过改变数组大小并检查上面示例中的 n
,您可以为您的平台推断 y
.对于 我的平台 y
是 1 个字.sizeof(word) 根据我是为 32 位还是 64 位架构编译而有所不同.
By varying the array size and inspecting n
in the example above, you can infer y
for your platform. For my platform y
is 1 word. The sizeof(word) varies depending on whether I'm compiling for a 32 bit or 64 bit architecture.
相关文章