用C ++声明数组

时间:2016-11-23 20:04:45

标签: c++ arrays c++11 stl

我是C ++的新手,目前正在自己​​学习一本书。这本书似乎说有几种数组取决于你如何声明它。我想动态数组和静态数组之间的区别对我来说很清楚。但我不明白STL std::array类和静态数组之间的区别。

STL std::array变量声明为:

std::array < int, arraySize > array1;

静态数组变量声明为:

int array1[arraySize];

这两者之间有根本区别吗?或者它只是语法而且两者基本相同?

8 个答案:

答案 0 :(得分:23)

std::array<>只是C风格数组的一个轻量级包装器,还有一些额外的好的接口成员函数(如beginend等)和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
}

Live on Coliru

答案 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风格的数组相似:

  • 它们都存储连续的对象序列
  • 它们都是聚合类型,因此可以使用aggregate initialization
  • 进行初始化
  • 它们的大小在编译时已知
  • 他们不使用动态内存分配

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::endstd::vectorstd::map等。

STL std::set的优点还在于它有一个std::array方法,可以让你获得元素数。要获得C风格数组的元素数,您必须编写size(),因此sizeof(cArray)/sizeof(cArray[0])看起来更具可读性吗?

您可以在此处获得完整参考:

http://en.cppreference.com/w/cpp/container/array

答案 6 :(得分:1)

通常你应该更喜欢std::array<T, size> array1;而不是T array2[size];,而且基础结构是相同的。

主要原因是std::array总是知道它的大小。您可以调用其size()方法来获取大小。而当你使用C风格的数组(即你所谓的“内置数组”)时,你总是必须将大小传递给使用该数组的函数。如果你以某种方式弄错了,你可能会导致缓冲区溢出,并且该函数会尝试读取/写入不再属于该数组的内存。 std::array不会发生这种情况,因为大小始终是清晰的。

答案 7 :(得分:1)

IMO,

  • 优点:它的效率很高,因为它不会使用比内置固定数组更多的内存。

  • 缺点:内置固定数组的std::array是一种稍微笨拙的语法,你必须明确指定数组长度(编译器不会从初始化程序中为你计算它)。