为什么C++不支持基于动态数组循环的范围?就是这样的:
int* array = new int[len];
for[] (int i : array) {};
Run Code Online (Sandbox Code Playgroud)
我刚刚发明了for[]与韵new[]和韵的说法delete[].据我所知,运行时具有可用数组的大小(否则delete[]无法工作),因此理论上,基于for循环的范围也可以使用.它不起作用的原因是什么?
use*_*042 12
它不起作用的原因是什么?
一个基于范围的循环
for(auto a : y) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
只是以下表达式的语法糖
auto endit = std::end(y);
for(auto it = std::begin(y); it != endit; ++it) {
auto a = *it;
// ...
}
Run Code Online (Sandbox Code Playgroud)
由于std::begin()和std::end()不能与普通指针一起使用,因此不能使用分配的指针来应用new[].
据我所知,运行时具有可用数组的大小(否则
delete[]无法工作)
如何delete[]跟踪分配的内存块new[](不一定与用户指定的大小相同)是完全不同的事情,编译器甚至可能甚至不知道这是如何实现的.
当你有这个:
int* array = new int[len];
Run Code Online (Sandbox Code Playgroud)
这里的问题是你调用的变量array根本不是数组.这是一个指针.这意味着它仅包含地址的一个对象(在此情况下,使用所创建的阵列的第一个元素new).
对于基于范围的工作,编译器需要两个地址,即数组的开头和结尾.
所以问题是编译器没有足够的信息来执行此操作:
// array is only a pointer and does not have enough information
for(int i : array)
{
}
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)int* array = new int[len]; for[] (int i : array) {}
有几点必须解决;我会一次解决他们一个。
运行时是否知道数组的大小?
在某些条件下,它必须。正如您所指出的,调用delete[]将调用每个元素的析构函数(按保留顺序),因此必须知道有多少。
但是,通过不指定元素的数量必须是已知的和可访问的,C++ 标准允许实现在不需要调用析构函数时省略它(std::is_trivially_destructible<T>::value计算结果为true)。
运行时能否区分指针和数组?
一般来说,没有。
当你有一个指针时,它可以指向任何东西:
This is the reason what delete[] exists, and using delete here would be incorrect. With delete[], you the user state: this pointer points to the first item of a heap-allocated array.
The implementation can then assume that, for example, in the 8 bytes preceding this first item it can find the size of the array. Without you guaranteeing this, those 8 bytes could be anything.
Then, why not go all the way and create
for[] (int i : array)?
There are two reasons:
for[] syntax, it would no longer be possible on a per-type basis.Let us be honest, new[] and delete[] are relics of an older time. They are incredibly awkward:
and unsafe to use:
There is generally no reason to use new[] and delete[] in modern C++. Most of the times a std::vector should be preferred; in the few instances where the capacity is superfluous, a std::dynarray is still better (because it keeps track of the size).
Therefore, without a valid reason to keep using these statements, there is no motivation to include new semantic constructs specifically dedicated to handling them.
And should anyone be motivated enough to make such a proposal:
std::variant), would also likely be held against them.I recommend that you simply use std::vector.