当前的标准草案明确指出放置new[]可能有空间开销:
这种开销可以应用于所有数组新表达式,包括那些引用库函数operator new [](std :: size_t,void*)和其他放置分配函数的表达式.开销的数量可能因新的一次调用而异.
所以大概他们有一些想法,为什么编译器需要这个开销.它是什么?编译器可以将此开销用于任何有用的东西吗?
在我的理解中,要破坏这个数组,唯一的解决方案是在一个循环中调用析构函数(我是否正确?),因为没有放置delete[](顺便说一下,我们不应该有delete[]正确的方法来破坏数组,不仅仅是它的元素?).因此编译器不必知道数组长度.
我认为这个开销不能用于任何有用的东西,编译器不会使用它(所以这在实践中不是问题).我用这个简单的代码检查了编译器:
#include <stdio.h>
#include <new>
struct Foo {
~Foo() { }
};
int main() {
char buffer1[1024];
char buffer2[1024];
float *fl = new(buffer1) float[3];
Foo *foo = new(buffer2) Foo[3];
printf("overhead for float[]: %d\n", (int)(reinterpret_cast<char*>(fl) - buffer1));
printf("overhead for Foo[] : %d\n", (int)(reinterpret_cast<char*>(foo) - buffer2));
}
Run Code Online (Sandbox Code Playgroud)
GCC和clang根本不使用任何开销.但是,MSVC使用8个字节的Foo情况.为什么MSVC会使用这种开销?
这是一些背景,为什么我提出这个问题.
之前有关于此主题的问题:
据我所知,这些问题的道德是避免使用放置new[],并new在循环中使用放置.但是这个解决方案不会创建一个数组,但是使用彼此相邻的元素(不是数组)operator[]是未定义的行为.这些问题更多的是关于如何避免安置new[],但这个问题更多的是关于"为什么?".
动态数组分配是特定于实现的。但是实现动态数组分配的常见做法是在开始之前存储其大小(我的意思是在第一个元素之前存储大小)。这与以下内容完全重叠:
表示数组分配开销;new 表达式的结果将从运算符 new[] 返回的值中偏移此量。
“放置删除”没有多大意义。所做delete的就是调用析构函数和释放内存。delete对所有数组元素调用析构函数并释放它。显式调用析构函数在某种意义上是“放置删除”。