为什么C++不支持基于动态数组循环的范围?

Bal*_*zay 19 c++

为什么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[](不一定与用户指定的大小相同)是完全不同的事情,编译器甚至可能甚至不知道这是如何实现的.


Gal*_*lik 6

当你有这个:

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)


Mat*_* M. 5

int* array = new int[len];
for[] (int i : array) {}
Run Code Online (Sandbox Code Playgroud)

有几点必须解决;我会一次解决他们一个。

运行时是否知道数组的大小?

在某些条件下,它必须。正如您所指出的,调用delete[]将调用每个元素的析构函数(按保留顺序),因此必须知道有多少。

但是,通过不指定元素的数量必须是已知的和可访问的,C++ 标准允许实现在不需要调用析构函数时省略它(std::is_trivially_destructible<T>::value计算结果为true)。

运行时能否区分指针和数组?

一般来说,没有。

当你有一个指针时,它可以指向任何东西:

  • a single item, or an item in an array,
  • the first item in an array, or any other,
  • an array on the stack, or an array on the heap,
  • just an array, or an array part of a larger object.

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:

  1. As mentioned, today an implementation can elide the size on a number of elements; with this new for[] syntax, it would no longer be possible on a per-type basis.
  2. It's not worth it.

Let us be honest, new[] and delete[] are relics of an older time. They are incredibly awkward:

  • the number of elements has to be known in advance, and cannot be changed,
  • the elements must be default constructible, or otherwise C-ish,

and unsafe to use:

  • the number of elements is inaccessible to the user.

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:

  • the inhibition of the current optimization, a violation of C++ philosophy of "You don't pay for what you don't use", would likely be held against them,
  • the inclusion of new syntax, when modern C++ proposals have gone to great lengths to avoid it as much as possible (to the point of having a library defined std::variant), would also likely be held against them.

I recommend that you simply use std::vector.

  • 遗憾的是,“std::dynarray”似乎不再是一个东西了。 (2认同)