C++ 中的有界数组与无界数组

bounded arrays vs unbounded arrays in C++

我偶然发现了 std::is_bounded_arraystd::is_unbounded_array,我也知道 std::make_unique 不支持有界数组。

有人可以阐明为什么会这样吗?创建有界数组与创建无界数组之间有什么区别?

编辑:这与 what is an unbounded array? 不同,因为那里提供的答案集中在无限数组上。这个问题更侧重于实践和实施方面。创建有界数组与无界数组有哪些不同的方法?为什么 std::make_unique 不支持有界数组?从编译器的角度来看,有界数组和无界数组有什么不同?我可以将有界数组转换为无界数组,反之亦然吗?

有界数组与无界数组数组相关的奇怪案例是 C++ 中为数不多的案例之一,其中对象的 声明类型 与 [=20 的声明类型不同=]其他地方的相同对象。即,当数组对象的(不完整)声明类型是未知边界数组时与声明类型是已知边界数组时。来自[basic.types]/6[强调我的]:

A class type (such as “class X”) might be incomplete at one point in a translation unit and complete later on; the type “class X” is the same type at both points. The declared type of an array object might be an array of incomplete class type and therefore incomplete; if the class type is completed later on in the translation unit, the array type becomes complete; the array type at those two points is the same type. The declared type of an array object might be an array of unknown bound and therefore be incomplete at one point in a translation unit and complete later on; the array types at those two points (“array of unknown bound of T” and “array of N T”) are different types. The type of a pointer to array of unknown bound, or of a type defined by a typedef declaration to be an array of unknown bound, cannot be completed. [ Example:

// ...

extern int arr[]; // the type of arr is incomplete

// ...

int arr[10]; // now the type of arr is complete

事实上,下面的程序是合式的:

#include <type_traits>

// declared type: array of unknown bound (and therefore incomplete)
extern int arr[];
static_assert(std::is_unbounded_array_v<decltype(arr)>);
static_assert(!std::is_bounded_array_v<decltype(arr)>);

// declared type: array of known bound (now the type of arr is complete)
int arr[10];
static_assert(!std::is_unbounded_array_v<decltype(arr)>);
static_assert(std::is_bounded_array_v<decltype(arr)>);

int main() {}

在C++中,“无界数组”更正式地称为“未知边界数组”,类似地,“有界数组”也称为“已知边界数组”。

您没有创建未知边界的数组对象。您可以通过 new 表达式创建不同边界的数组,并使用单个 unique_ptr 来管理它们。

std::unique_ptr<int[]> p{new int[3]}; // p manages an array of size 3
p.reset(new int[4]); // now p manages an array of size 4

(在 C++ 中,“数组边界”和“数组大小”是同义词。)

make_unique 是为了让你不需要直接使用 new.

auto p = std::make_unique<int[]>(3); // p manages an array of size 3
p = std::make_unique<int[]>(4); // now p manages an array of size 4

另一方面,您永远不需要 unique_ptr 有界数组。您只需定义数组:使用 int array[3] 而不是 std::unique_ptr<int[3]> pointer_to_array;。 (实际上,std::unique_ptr<int[3]> p{new int[3]}; 格式错误。)因此 std::make_unique 不会尝试支持这种明显不存在的用例。

For the standpoint of compiler, what all is different between a bounded array and an unbounded one?

它们只是不同的类型。

Can I cast a bounded array to unbounded array and vice-versa?

没有也没有。既没有隐式也没有显式转换为数组类型。 “已知边界数组”类型的表达式可以隐式转换为对未知边界数组的引用,并且可以进行指针转换,这要归功于 P0388R4.