在 C++ 中,如果必须在编译时确定大小,std::array 的意义何在?
In C++ what is the point of std::array if the size has to be determined at compile time?
请原谅我的无知,在我看来 std::array
应该是常规数组的 STL 替代品。但是因为数组大小必须作为模板参数传递,所以它阻止我们创建大小仅在运行时已知的 std::array
。
std::array<char,3> nums {1,2,3}; // Works.
constexpr size_t size = 3;
std::array<char,size> nums {1,2,3}; // Works.
const buf_size = GetSize();
std::array<char, buf_size> nums; // Doesn't work.
我假设 C++ 中数组的一个非常重要的用例是基于运行时输入创建固定大小的数据结构(比如为读取文件分配缓冲区)。
我使用的解决方法是:
// Create a array pointer for on-the-spot usecases like reading from a file.
char *data = new char[size];
...
delete[] data;
或:
// Use unique_ptr as a class member and I don't want to manage the memory myself.
std::unique_ptr<char[]> myarr_ = std::unique_ptr<char[]>(new char[size]);
如果我不关心固定尺寸,我知道我可以使用 std::vector<char>
和预定义尺寸如下:
std::vector<char> my_buf (buf_size);
为什么 std::array
的设计者选择忽略这个用例?也许我不明白 std::array
.
的真正用例
编辑:我想另一种表达我的问题的方式也可能是——为什么设计者选择将大小作为模板参数而不是构造函数参数传递?选择后者是否会导致难以提供 std::array
目前拥有的功能?对我来说,这似乎是一种深思熟虑的设计选择,我不明白为什么。
std::array
是 C 风格数组的替代品。
C++ 标准不允许在没有编译时定义大小的情况下声明 C 样式数组。
易于编程
std::array
促进了 std::vector
中使用的几个有益的界面和习语。对于普通的 C 风格数组,不能有 .size()
(没有 sizeof
hack)、.at()
(超出范围的异常)、front()/back()
、迭代器等。一切都必须手工编码。
许多程序员可能会选择 std::vector
即使对于编译时已知大小的数组,只是因为他们想利用上述编程方法。但这夺走了编译时固定大小数组的性能。
因此,std::array
是由库制造商提供的,以阻止 C 风格的数组,并且在编译时已知大小时避免 std::vector
s。
我理解的两个主要原因是:
std::array
实现 STL 的集合类型接口,允许将 std::array
按原样传递给接受任何 STL 迭代器的函数和方法。
- 防止数组指针衰减...(下)
...这是跨 function/method 边界保留类型信息,因为它防止 Array Pointer Decay.
给定一个裸数组C/C++,你可以通过4种方式将它作为参数传递给另一个函数:
void by_value1 ( const T* array )
void by_value2 ( const T array[] )
void by_pointer ( const T (*array)[U] )
void by_reference( const T (&array)[U] )
by_value1
和 by_value2
在语义上是相同的并且会导致指针衰减,因为接收函数不知道 sizeof
数组。
by_pointer
和 by_reference
都要求 U
通过已知的编译时常量,但保留 sizeof
信息。
因此,如果您通过使用 by_pointer
或 by_reference
避免数组衰减,您现在每次更改数组大小时都会遇到维护问题,您必须手动更新所有调用站点在 U
.
中具有该尺寸
通过使用 std::array
可以为您处理这些函数 template
函数,其中 U
是参数(当然,您可以 still 使用 by_pointer
和 by_reference
技术,但语法更混乱)。
...所以 std::array
adds a 5th way:
template<typename T, size_t N>
void by_stdarray( const std::array<T,N>& array )
请原谅我的无知,在我看来 std::array
应该是常规数组的 STL 替代品。但是因为数组大小必须作为模板参数传递,所以它阻止我们创建大小仅在运行时已知的 std::array
。
std::array<char,3> nums {1,2,3}; // Works.
constexpr size_t size = 3;
std::array<char,size> nums {1,2,3}; // Works.
const buf_size = GetSize();
std::array<char, buf_size> nums; // Doesn't work.
我假设 C++ 中数组的一个非常重要的用例是基于运行时输入创建固定大小的数据结构(比如为读取文件分配缓冲区)。
我使用的解决方法是:
// Create a array pointer for on-the-spot usecases like reading from a file.
char *data = new char[size];
...
delete[] data;
或:
// Use unique_ptr as a class member and I don't want to manage the memory myself.
std::unique_ptr<char[]> myarr_ = std::unique_ptr<char[]>(new char[size]);
如果我不关心固定尺寸,我知道我可以使用 std::vector<char>
和预定义尺寸如下:
std::vector<char> my_buf (buf_size);
为什么 std::array
的设计者选择忽略这个用例?也许我不明白 std::array
.
编辑:我想另一种表达我的问题的方式也可能是——为什么设计者选择将大小作为模板参数而不是构造函数参数传递?选择后者是否会导致难以提供 std::array
目前拥有的功能?对我来说,这似乎是一种深思熟虑的设计选择,我不明白为什么。
std::array
是 C 风格数组的替代品。
C++ 标准不允许在没有编译时定义大小的情况下声明 C 样式数组。
易于编程
std::array
促进了 std::vector
中使用的几个有益的界面和习语。对于普通的 C 风格数组,不能有 .size()
(没有 sizeof
hack)、.at()
(超出范围的异常)、front()/back()
、迭代器等。一切都必须手工编码。
许多程序员可能会选择 std::vector
即使对于编译时已知大小的数组,只是因为他们想利用上述编程方法。但这夺走了编译时固定大小数组的性能。
因此,std::array
是由库制造商提供的,以阻止 C 风格的数组,并且在编译时已知大小时避免 std::vector
s。
我理解的两个主要原因是:
std::array
实现 STL 的集合类型接口,允许将std::array
按原样传递给接受任何 STL 迭代器的函数和方法。- 防止数组指针衰减...(下)
...这是跨 function/method 边界保留类型信息,因为它防止 Array Pointer Decay.
给定一个裸数组C/C++,你可以通过4种方式将它作为参数传递给另一个函数:
void by_value1 ( const T* array )
void by_value2 ( const T array[] )
void by_pointer ( const T (*array)[U] )
void by_reference( const T (&array)[U] )
by_value1
和by_value2
在语义上是相同的并且会导致指针衰减,因为接收函数不知道sizeof
数组。by_pointer
和by_reference
都要求U
通过已知的编译时常量,但保留sizeof
信息。
因此,如果您通过使用 by_pointer
或 by_reference
避免数组衰减,您现在每次更改数组大小时都会遇到维护问题,您必须手动更新所有调用站点在 U
.
通过使用 std::array
可以为您处理这些函数 template
函数,其中 U
是参数(当然,您可以 still 使用 by_pointer
和 by_reference
技术,但语法更混乱)。
...所以 std::array
adds a 5th way:
template<typename T, size_t N>
void by_stdarray( const std::array<T,N>& array )