好吧,我认为这并不重要,但是由于程序必须存储长度,因为 delete[] 反正我们为什么不能得到这个“存储的信息”?
9 回答
实现只需要存储长度,并且通常仅在类型不是可简单破坏的情况下(即,它需要生成对析构函数的调用)并且数组是使用 new[] 运算符创建的。
由于数组类型的该属性与数组的大小无关,因此将长度“cookie”简单地称为私有实现细节更为优雅。
要获取完整数组对象的长度(不仅仅是指针),您可以使用std::extent< decltype( arr ) >::value
or std::end( arr ) - std::begin( arr )
。
new[]
与带有析构函数的类一起使用是一种代码味道。std::vector
改为考虑。开销与原始new[]
(考虑到需要分配的所有字节,无论它们在哪里)是一个指针的字节价值,其好处是数不清的。
考虑以下情况:
char* a = new char[100];
现在a
需要指向一个至少有 100 个字符大的缓冲区,但系统可能已经分配了一个更大的缓冲区来完成这个。
考虑到这一点,我们可以看到系统可以立即忘记程序要求的大小,只要它以后仍然可以正确地释放缓冲区。(通过记住分配缓冲区的大小或使用一些只需要指向开始的指针的智能数据结构进行内存分配)
因此,在一般情况下,您要查找的信息实际上并不存储在任何地方。
并非所有数组都由new
.
void f(int* arr, size_t n)
{
length(arr); // ???
}
int main()
{
int a[5];
f(a);
}
虽然写起来很简单,只是 call (std::end(arr) - std::begin(arr))
,虽然它只适用于数组,而不是指向数组开头的指针。
我的理解是,c++ 的理念是不强迫人们使用任何具有潜在成本的功能,除非不可避免。
存储此信息可能会产生额外费用,如果用户不需要该信息,他们可能不想支付该费用。而且,如果您想要自己存储长度是微不足道的,因此没有理由提供一种语言功能,这对使用数组的每个人来说都是有成本的。
对于正确的数组,即int a[length]
,您已经拥有该功能:只需执行
#define length(A) (sizeof(A) / sizeof(*A))
你就完成了。
如果您正在谈论获取指针指向的数组的长度,那么指针和数组是两个不同的概念,将它们耦合是没有意义的,即使适当的数组在需要时“衰减”到指针并且您通过指针访问数组算术。
但是即使我们不考虑这一点并谈论技术方面,C++
运行时也可能不知道您的数组的长度是多少,因为new
可以依赖malloc
,它以特定的方式存储数组的长度,这是可以理解的only by free
:C++
运行时仅在您有非空析构函数时才存储额外信息。好乱的图啊
因为它取决于存储此信息的实现。所以没有一般的方法来做一个长度(数组)
长度肯定不会存储在所有实现中。例如,C++ 允许垃圾收集(例如 boehmgc),许多收集器不需要知道长度。在传统的分配器中,存储的长度通常会大于实际长度,即分配的长度,而不是使用的长度。
但是,数组的长度究竟是多少?是数组中的字节数还是数组中的元素数?
例如:对于某些 100 字节大小的 A 类,
A* myArray = 新 A[100];
length(myArray) 应该返回 100 还是 100 * 100?有人可能想要 100,有人可能想要 10000。所以,这两者都没有真正的论据。
与支持语言中的“数组”最相似的 c++ 类型length(array)
是std::vector<>
,并且它确实具有std::vector<>::size()
.
当然,普通[]
数组的大小在大小是明确的范围内是编译器知道的,但是可以将它们传递给编译器不知道大小的范围。与必须支持疑问句的语言相比,这为 c++ 提供了更多length
处理类数组数据的方法(因为它们必须确保始终传递大小)。