数组放置新需要缓冲区中未指定的开销?

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.

相关文章