我是C ++的新手,目前正在自己学习一本书。这本书似乎说有几种数组取决于你如何声明它。我想动态数组和静态数组之间的区别对我来说很清楚。但我不明白STL std::array
类和静态数组之间的区别。
STL std::array
变量声明为:
std::array < int, arraySize > array1;
静态数组变量声明为:
int array1[arraySize];
这两者之间有根本区别吗?或者它只是语法而且两者基本相同?
答案 0 :(得分:23)
std::array<>
只是C风格数组的一个轻量级包装器,还有一些额外的好的接口成员函数(如begin
,end
等)和typedef
s ,大致定义为
template<typename T, size_t N>
class array
{
public:
T _arr[N];
T& operator[](size_t);
const T& operator[](size_t) const;
// other member functions and typedefs
}
一个基本的区别是前者可以通过值传递,而后者只能传递指向其第一个元素的指针,或者你可以通过引用传递它,但是你不能将它复制到函数中(除了通过std::copy
或手动)。
一个常见的错误是假设每次将C样式数组传递给函数时,由于数组衰减为指针而导致其大小丢失。这并非总是如此。如果您通过引用传递它,则可以恢复其大小,因为在这种情况下没有衰减:
#include <iostream>
template<typename T, size_t N>
void f(T (&arr)[N]) // the type of arr is T(&)[N], not T*
{
std::cout << "I'm an array of size " << N;
}
int main()
{
int arr[10];
f(arr); // outputs its size, there is no decay happening
}
答案 1 :(得分:8)
这两者之间的主要区别很重要。
除了STL给你的好方法,在将std::array
传递给函数时,没有衰减。这意味着,当您在函数中收到std::array
时,它仍然是std::array
,但是当您将int[]
数组传递给函数时,它会有效地衰减为int*
指针和数组的大小都会丢失。
这种差异很大。一旦丢失了数组大小,代码现在容易出现很多错误,因为您必须手动跟踪数组大小。 sizeof()
返回指针类型的大小,而不是数组中元素的数量。这会强制您使用process(int *array, int size)
等接口手动跟踪数组大小。这是一个很好的解决方案,但容易出错。
参见Bjarne Stroustroup的指南:
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rp-run-time
使用更好的数据类型可以避免这种情况,std::array
是为许多其他STL类设计的。
作为旁注,除非有充分的理由使用固定大小的数组,std::vector
可能是一个更好的选择作为连续的内存数据结构。
答案 2 :(得分:6)
std::array
和C风格的数组相似:
std::array
的一个重要优点是它可以通过值传递,并且不会像C风格的数组一样隐式衰减到指针。
答案 3 :(得分:5)
在这两种情况下,都会在堆栈上创建数组。
但是,STL的std::array
类模板比第二种情况的“原始”C类数组语法提供了一些优势:
int array1[arraySize];
例如,对于std::array
,您有一个典型的STL接口,使用size
等方法(可用于查询数组的元素数),front
,{{1} },back
等
您可以找到更多详情here。
答案 4 :(得分:3)
这两者之间有根本区别吗?或者它只是语法而两者基本相同?
原始c风格数组(内置数组)与std::array
之间存在许多差异。
从参考文档中可以看出,有许多可用的原始数据操作:
例如:元素访问
at()
front()
back()
data()
std::array
的基础数据类型仍然是一个原始数组,但是用&#34;语法糖&#34; (如果这应该是您关注的话)点缀。
答案 5 :(得分:2)
std::array<>
和C风格数组的主要区别在于前者是一个包裹后者的类。该类具有begin()
和end()
方法,允许std::array
个对象作为参数轻松传递给期望迭代器的STL算法(请注意,C样式数组也可以通过非成员{{ 1}} / std::begin
方法)。第一个指向数组的开头,第二个指向超出其结束的一个元素。您可以使用其他STL容器看到此模式,例如std::end
,std::vector
,std::map
等。
STL std::set
的优点还在于它有一个std::array
方法,可以让你获得元素数。要获得C风格数组的元素数,您必须编写size()
,因此sizeof(cArray)/sizeof(cArray[0])
看起来更具可读性吗?
您可以在此处获得完整参考:
答案 6 :(得分:1)
通常你应该更喜欢std::array<T, size> array1;
而不是T array2[size];
,而且基础结构是相同的。
主要原因是std::array
总是知道它的大小。您可以调用其size()方法来获取大小。而当你使用C风格的数组(即你所谓的“内置数组”)时,你总是必须将大小传递给使用该数组的函数。如果你以某种方式弄错了,你可能会导致缓冲区溢出,并且该函数会尝试读取/写入不再属于该数组的内存。 std::array
不会发生这种情况,因为大小始终是清晰的。
答案 7 :(得分:1)
IMO,
优点:它的效率很高,因为它不会使用比内置固定数组更多的内存。
缺点:内置固定数组的std::array
是一种稍微笨拙的语法,你必须明确指定数组长度(编译器不会从初始化程序中为你计算它)。