用std :: array替换固定大小的数组?

时间:2014-03-21 23:04:47

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

使用遗留代码,我问自己应该用新的std :: array替换固定大小的C样式数组吗? E. g。

static const int TABLE_SIZE = 64;
double table[TABLE_SIZE];

替换为

std::array<double, TABLE_SIZE> table;

虽然我看到将std :: vector用于可变大小数组的好处,但我没有看到它们具有固定大小。 table.size()无论如何都是已知的,std::begin(), std::end()因为自由函数也可用于具有C风格数组的STL算法。因此,除了更符合标准外,我还能错过更多的好处吗?替换所有事件是否值得工作还是被认为是最佳实践?

7 个答案:

答案 0 :(得分:10)

AFAIK std::array只提供更好的类似STL的接口来处理而不是正常的C阵列。在性能和功能方面,两个选项可以大致相同,但std::array可以用作标准容器。

另一个特性:它们可能被视为tuples,因为它们提供类似元组的访问功能。

最后但并非最不重要的是user2079303注意到:如果您的代码将由新手程序员使用,它可以在将其作为参数传递时阻止数组衰减过程。

如果您想知道是否应该用std :: arrays替换所有C风格的数组,那么如果您要开发一些新的功能和/或重写,答案是肯定的。您的一些代码可以利用这些功能。如果您只是简单地用带有std :: arrays的C数组替换它(不接触任何其他内容),那么它可能是不值得的。

答案 1 :(得分:6)

还有一件事我还没有提到:std::array::at()。堆栈损坏可能非常讨厌调试,并且由于堆栈损坏导致的错误可能会隐藏很长一段时间。 :(与Address Sanitizer相比,这种情况已经变得有点了。但是,我更喜欢检查地址消毒剂。

在我看来,绑定检查元素访问本身就足以使用std::array而不是C样式数组。

答案 2 :(得分:5)

std::array的另一个功能是可以复制分配;

std::array<int, 3> a = {1, 2, 3};
std::array<int, 3> b = {4, 5, 6};

std::array<int, 3> c = a;         // copy-construction
a = b;                            // copy-assignment

答案 3 :(得分:4)

恕我直言,你绝不应该在没有充分理由的情况下改变工作遗留代码。如果你正在开发一个增强功能,或者修复一个bug,那么无论如何都要修改有问题的文件然后我会说确保继续进行更改。否则,你可能有更好的时间与你的时间有关。总是存在与更改源代码相关的风险,这可能会导致您在执行更高效的工作时进行大量的调试。

答案 4 :(得分:4)

这取决于用例。性能和空间方面,它们应该是相同的,除了std::array携带的大小成员。编辑:甚至大小将被优化。所以即使在空间方面它也是相同的。实现通常可以:

template <class T, std::size_t N>
class array {
...
public:
    contsexpr std::size_t size() const { return N; }

}

远离存储字符串的大小。

传递它时,

std::array<T, N>不会衰减到指针。但是在你的用例中你有一个全局变量,我想。我不会改变它已经起作用的只是让它看起来更好。

另一方面,如果您想将任意大小的std::array传递给某个函数,则必须对其进行模板化处理:

template <std::size_t N>
void f(std::array<MyT, N> const & arr);

std::array的优点

  • 更安全,他们不会腐烂指针。
  • 它们的大小。

std::array

的缺点
  • 如果您想要使用std::array的一般功能, 你必须在标题中作为模板。

在C数组中,您可以这样做:

void f(MyT const * arr, std::size_t size);

它可以用于任何数组,无论长度如何。 这样安全性较低,但在.cpp中隐藏依赖项更方便 文件,因为以后你可以在.cpp文件中编写函数。

但正如我所说,考虑到您的用例,请选择。我不会 更改正在工作且不会被曝光的代码(例如, 如果它是一个永远不被视为函数参数的全局变量) 以任何不安全的方式。

答案 5 :(得分:2)

我认为std :: array比c风格的数组有许多优点。因此,有必要尝试替换所有出现或至少开始使用std :: array而不是c-style。有关更多信息,我们可以看一下Bjarne Stroustrup的C ++ 11 FAQ提到的here

  • 除了保存元素之外,它没有空间开销。
  • 它不使用免费商店,可以使用初始化列表
  • 进行初始化
  • 它知道它的大小(元素数量)。
  • 除非您明确要求,否则它不会转换为指针。
  • 标准阵列的功能使其对嵌入式系统编程(以及类似的约束,性能关键或安全关键任务)具有吸引力。

换句话说,它非常像一个没有问题的内置数组。

关于你对table.size()的观点是已知的,但只有在有人在定义它的上下文中使用数组时它才有效。如果我们需要将它传递给其他函数,那么它就不知道了,我们必须通过它。

答案 6 :(得分:1)

有许多事情:

  • 成员函数,因此它看起来像标准库中的每个其他序列
  • 元组访问(gettuple_sizetuple_element)与编译时间检查边界访问
  • 不会衰减为指针

第一点非常明显,主要是通用代码的优点。第二点有点模糊:从语义arrayS开始只是退化tupleS(当然tupleS不保证在内存中顺序存储)。这样处理它们是有道理的,并且处理元组的代码也可以在很大程度上与数组一起工作。第三点是一个很好的奖励,并为代码增加了一些安全性。