C ++不会告诉你动态数组的大小。 但为什么?
我知道在C ++中没有办法获得动态创建的数组的大小,例如:
int* a;
a = new int[n];
我想知道的是:为什么? 人们是否在C ++规范中忘记了这一点,或者是否存在技术原因?
这些信息是否存储在某个地方? 毕竟,这个命令
delete[] a;
似乎知道它有多少内存释放,所以在我看来, delete[]
有知道的大小某种方式a
。
您经常会发现内存管理器将仅分配一定数量的空间,例如64个字节。
所以,你可能会要求新的int [4],即16个字节,但内存管理器将为你的请求分配64个字节。 为了释放这个内存,它不需要知道你要求多少内存,只需要它分配给你一个64字节的块。
接下来的问题可能是,它能否存储所需的尺寸? 这是额外的开销,并非每个人都愿意付费。 例如Arduino Uno只有2k的RAM,在这种情况下,每个分配4个字节突然变得很重要。
如果你需要这个功能,那么你有std :: vector(或等价的),或者你有更高级的语言。 C / C ++的设计目的是使您能够尽可能少地使用开销,这只是一个例子。
这是从“不支付你不需要的东西”这一基本规则中得出的结论。 在你的例子中delete[] a;
不需要知道数组的大小,因为int没有析构函数。 如果你写过:
std::string* a;
a = new std::string[n];
...
delete [] a;
然后, delete
必须调用析构函数(并且需要知道要调用多少) - 在这种情况下, new
函数必须保存该计数。 然而,由于它不需要在任何场合保存,Bjarne决定不允许访问它。
(事后看来,我认为这是一个错误...)
即使使用int
,事情必须知道分配内存的大小,但是:
为了对齐和便利的原因,许多分配器将大小凑成一些方便的倍数(比如64字节)。 分配器知道一个块的长度是64字节 - 但它不知道这是否是因为n
是1 ...或16。
C ++运行时库可能无法访问分配块的大小。 例如,如果new
和delete
正在使用malloc
并且是free
的,那么C ++库无法知道malloc
返回的块的大小。 (通常当然, new
和malloc
都是同一个库的一部分 - 但并不总是如此。)
一个根本的原因是指向T
的动态分配数组的第一个元素的指针与指向任何其他T
的指针没有区别。
考虑一个虚构的函数,它返回一个指针指向的元素的数量。
我们称之为“大小”。
听起来很不错,对吧?
如果不是因为所有的指针都是相同的:
char* p = new char[10];
size_t ps = size(p+1); // What?
char a[10] = {0};
size_t as = size(a); // Hmm...
size_t bs = size(a + 1); // Wut?
char i = 0;
size_t is = size(&i); // OK?
你可能会争辩说第一个应该是9
,第二个10
,第三个9
和最后1
,但为了完成这个,你需要在每一个对象上添加一个“大小标记”。
char
在64位机器上需要128位的存储空间(因为对齐)。 这比所需要的多十六倍。
(以上,十个字符的数组a
需要至少168个字节。)
这可能很方便,但也是不可接受的昂贵。
当然,如果参数真的是指向默认operator new
的动态分配的第一个元素的指针,您当然可以设想一个定义良好的版本,但这不像人们想象的那么有用。
上一篇: C++ doesn't tell you the size of a dynamic array. But why?
下一篇: C++ replacement for C99 VLAs (goal: preserve performance)