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

时间:2021-12-28 21:42:19

Working with legacy code, I asked myself should I replace fixed sized C-style arrays with the new std::array? E. g.

使用遗留代码时,我问自己是否应该用新的std::array替换固定大小的c风格数组?e . g。

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

replace with

替换为

std::array<double, TABLE_SIZE> table;

While I see the benefits from using std::vector for variable size arrays, I don't see them with fixed size. table.size() is known anyways, std::begin(), std::end() as free functions can be used for STL-algorithms with C-style arrays too. So besides being more standard compliant, do I miss more benefits? Is it worth the work to replace all occurrences or is it considered to be best practice?

虽然我看到了使用std::vector处理可变大小数组的好处,但我没有看到它们具有固定大小。表.size()是众所周知的,std::begin(), std::end()作为*函数,也可以用于c风格数组的stl算法。因此,除了更符合标准,我还会错过更多的好处吗?替换所有发生的事情是否值得,或者它被认为是最佳实践?

7 个解决方案

#1


10  

AFAIK std::array just provides a nicer STL-like interface to deal with rather than normal C-arrays. In terms of performances and capabilities the two choices boil down to be pretty much the same but std::array can be used as a standard container.

AFAIK std::数组只是提供了一个更好的类似stl的接口来处理,而不是普通的c -数组。就性能和性能而言,这两种选择基本上是相同的,但std::array可以用作标准容器。

Another feature: they might be treated like tuples since they provide tuple-like access functions.

另一个特性是:它们可以像元组一样处理,因为它们提供了类似于tupley的访问函数。

Last but not the least as user2079303 noticed: if your code is going to be used by novice programmers, it can prevent the array decaying process when passing it as an argument.

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

If you're wondering if you should just replace all your C-style arrays with std::arrays, the answer is yes if you're going to exploit some of the newly available features and/or rewrite some of your code to take advantage of those capabilities. If you're just plain substituting C-arrays with std::arrays (without touching anything else) it might not be worth it.

如果您不知道是否应该用std::array替换所有c样式的数组,那么答案是肯定的,如果您打算利用一些新可用的特性并/或重写一些代码以利用这些功能。如果只是简单地用std:::array替换c -array(不涉及任何其他内容),那么它可能不值得。

#2


6  

There is one more thing that I don't see mentioned yet: std::array::at(). Stack corruptions can be really nasty to debug and bugs due to stack corruption can hide for a long while. :( The situtation has become somewhat better with Address Sanitizer. Still, I prefer bound checking over address sanitizer.

还有一件事我还没有提到:std::array::at()。栈腐败非常难以调试,栈腐败导致的bug可能会隐藏很长一段时间。当前位置用地址消毒剂处理已好些了。尽管如此,我还是喜欢绑定检查而不是地址消毒剂。

In my opinion bound-checked element access is enough reason in itself to use std::array rather than C style arrays.

在我看来,有界检查的元素访问本身就足以让我们使用std:::array而不是C风格的数组。

#3


5  

An additional feature that std::array has is that it can be copy-assigned;

std::数组的另一个特性是它可以被复制;

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

#4


4  

IMHO, you should never change working, legacy code without a really good reason. If you are developing an enhancement, or fixing a bug and the files in question were going to be modified anyway then I'd say sure go ahead and make the change. Otherwise, you probably have better things to do with your time. There is always risk associated with changing source code that can lead to an extensive amount of time debugging when you could have been doing more productive things.

IMHO,如果没有一个很好的理由,你不应该改变工作,遗留代码。如果您正在开发一个增强,或者正在修复一个bug,而相关的文件无论如何都将被修改,那么我想说,请继续进行修改。否则,你可能有更好的事情要做。当您本来可以做更有成效的事情时,更改源代码总是会带来大量的时间调试的风险。

#5


4  

It depends on the use case. Performance and space-wise, they should be identical, except for the size member that std::array carries. EDIT: Even the size will be optimized out. So it´s identical even space-wise. Implementations usually can do:

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

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

}

And get away storing the size of the string.

然后存储字符串的大小。

std::array<T, N>won't decay to a pointer when passing it around. But in your use case you have a global variable, I guess. I wouldn´t change what it's already working just for making it look nicer.

数组 在传递时不会衰减到指针。但是在你的用例中你有一个全局变量。我就´t改变它已经工作只是为了让它看起来更好。 ,>

On the other hand, if you want to pass an std::arrayof any size to a function, you will have to template it:

另一方面,如果您想将任何大小的std::arrayof传递给一个函数,您必须将其模板化:

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

Pros of std::array

优点的std::数组

  • Safer, they don't decay to pointers.
  • 更安全的是,它们不会腐烂成指针。
  • They carry the size.
  • 他们携带的大小。

Cons of std::array

缺点的std::数组

  • If you want a general function taking std::array, you will have to do it in the header as a template.
  • 如果您想要使用std:::array的通用函数,就必须在header中作为模板来完成。

In C arrays, you can do this:

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

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

and it would work with any array, no matter the length. This is less safe BUT more convenient to hide dependencies in .cpp files, since later you can code the function inside a .cpp file.

它可以作用于任何数组,无论长度。这虽然不太安全,但是在.cpp文件中隐藏依赖项更方便,因为以后可以在.cpp文件中编写函数。

But as I said, taking into account your use case, choose. I wouldn't change code that is working and is not gonna be exposed (for example, if it is a global that is never taken as a parameter in functions) in any unsafe way.

但是正如我所说,考虑到您的用例,选择。我不会以任何不安全的方式更改正在运行和不会被公开的代码(例如,如果它是一个全局变量,在函数中从未被作为参数)。

#6


2  

I think std::array has many advantages over c-style arrays. So it is worthwhile to work to replace all occurrences or at least start using the std::array instead of c-style. For more information we can look here mentioned by C++11 FAQ by Bjarne Stroustrup.

我认为std::array比c风格的数组有很多优点。因此,有必要替换所有出现的情况,或者至少开始使用std::array而不是c样式。要了解更多信息,我们可以参考Bjarne Stroustrup在这里提到的c++ 11 FAQ。

  • It has no space overheads beyond what it needs to hold its elements.
  • 它没有多余的空间来容纳它的元素。
  • It does not use free store,and it can be initialized with an initializer list
  • 它不使用free store,并且可以使用初始化列表初始化它
  • It knows its size (number of elements).
  • 它知道它的大小(元素的数量)。
  • It doesn't convert to a pointer unless you explicitly ask it to.
  • 它不会转换为指针,除非你明确地要求它。
  • standard array's features makes it attractive for embedded systems programming (and similar constrained, performance-critical, or safety critical tasks) .
  • 标准数组的特性使得它对嵌入式系统编程(以及类似的受限、性能关键或安全关键任务)具有吸引力。

In other words, it is very much like a built-in array without the problems.

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

Regarding your point to table.size() is known, but it is valid only if somebody use the array in the context where it has been defined. If we need to pass it to some other function, then it is not known and we had to pass it.

关于表的点。size()是已知的,但是只有当某人在定义数组的上下文中使用数组时才有效。如果我们需要将它传递给其他函数,那么它是未知的,我们必须传递它。

#7


1  

There is a bunch of things:

有很多东西:

  • member functions so it looks like every other sequence in the standard library
  • 成员函数,所以它看起来像标准库中的其他序列
  • tuple like access (get, tuple_size, tuple_element) with compile time checked bounds access
  • 类似tuple的访问(get、tuple_size、tuple_element)具有编译时检查的边界访问
  • does not decay to a pointer
  • 它不会向指针衰减吗

The first point is pretty obvious and mainly a benefit in generic code. The second point is a little obscure: from a semantic arrayS are nothing else but degenerate tupleS (of course tupleS do not guarantee sequential storage in memory). Treating them as such makes sense and code working on tuples can work largely with arrays as well. The third point is a nice bonus and adds a little safety to code.

第一点很明显,主要是对通用代码的好处。第二点有点模糊:从语义数组中除了退化元组之外什么都不是(当然元组不保证在内存中进行顺序存储)。这样处理它们是有意义的,处理元组的代码在很大程度上也可以处理数组。第三点是一个不错的奖励,为代码增加了一点安全性。

#1


10  

AFAIK std::array just provides a nicer STL-like interface to deal with rather than normal C-arrays. In terms of performances and capabilities the two choices boil down to be pretty much the same but std::array can be used as a standard container.

AFAIK std::数组只是提供了一个更好的类似stl的接口来处理,而不是普通的c -数组。就性能和性能而言,这两种选择基本上是相同的,但std::array可以用作标准容器。

Another feature: they might be treated like tuples since they provide tuple-like access functions.

另一个特性是:它们可以像元组一样处理,因为它们提供了类似于tupley的访问函数。

Last but not the least as user2079303 noticed: if your code is going to be used by novice programmers, it can prevent the array decaying process when passing it as an argument.

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

If you're wondering if you should just replace all your C-style arrays with std::arrays, the answer is yes if you're going to exploit some of the newly available features and/or rewrite some of your code to take advantage of those capabilities. If you're just plain substituting C-arrays with std::arrays (without touching anything else) it might not be worth it.

如果您不知道是否应该用std::array替换所有c样式的数组,那么答案是肯定的,如果您打算利用一些新可用的特性并/或重写一些代码以利用这些功能。如果只是简单地用std:::array替换c -array(不涉及任何其他内容),那么它可能不值得。

#2


6  

There is one more thing that I don't see mentioned yet: std::array::at(). Stack corruptions can be really nasty to debug and bugs due to stack corruption can hide for a long while. :( The situtation has become somewhat better with Address Sanitizer. Still, I prefer bound checking over address sanitizer.

还有一件事我还没有提到:std::array::at()。栈腐败非常难以调试,栈腐败导致的bug可能会隐藏很长一段时间。当前位置用地址消毒剂处理已好些了。尽管如此,我还是喜欢绑定检查而不是地址消毒剂。

In my opinion bound-checked element access is enough reason in itself to use std::array rather than C style arrays.

在我看来,有界检查的元素访问本身就足以让我们使用std:::array而不是C风格的数组。

#3


5  

An additional feature that std::array has is that it can be copy-assigned;

std::数组的另一个特性是它可以被复制;

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

#4


4  

IMHO, you should never change working, legacy code without a really good reason. If you are developing an enhancement, or fixing a bug and the files in question were going to be modified anyway then I'd say sure go ahead and make the change. Otherwise, you probably have better things to do with your time. There is always risk associated with changing source code that can lead to an extensive amount of time debugging when you could have been doing more productive things.

IMHO,如果没有一个很好的理由,你不应该改变工作,遗留代码。如果您正在开发一个增强,或者正在修复一个bug,而相关的文件无论如何都将被修改,那么我想说,请继续进行修改。否则,你可能有更好的事情要做。当您本来可以做更有成效的事情时,更改源代码总是会带来大量的时间调试的风险。

#5


4  

It depends on the use case. Performance and space-wise, they should be identical, except for the size member that std::array carries. EDIT: Even the size will be optimized out. So it´s identical even space-wise. Implementations usually can do:

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

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

}

And get away storing the size of the string.

然后存储字符串的大小。

std::array<T, N>won't decay to a pointer when passing it around. But in your use case you have a global variable, I guess. I wouldn´t change what it's already working just for making it look nicer.

数组 在传递时不会衰减到指针。但是在你的用例中你有一个全局变量。我就´t改变它已经工作只是为了让它看起来更好。 ,>

On the other hand, if you want to pass an std::arrayof any size to a function, you will have to template it:

另一方面,如果您想将任何大小的std::arrayof传递给一个函数,您必须将其模板化:

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

Pros of std::array

优点的std::数组

  • Safer, they don't decay to pointers.
  • 更安全的是,它们不会腐烂成指针。
  • They carry the size.
  • 他们携带的大小。

Cons of std::array

缺点的std::数组

  • If you want a general function taking std::array, you will have to do it in the header as a template.
  • 如果您想要使用std:::array的通用函数,就必须在header中作为模板来完成。

In C arrays, you can do this:

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

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

and it would work with any array, no matter the length. This is less safe BUT more convenient to hide dependencies in .cpp files, since later you can code the function inside a .cpp file.

它可以作用于任何数组,无论长度。这虽然不太安全,但是在.cpp文件中隐藏依赖项更方便,因为以后可以在.cpp文件中编写函数。

But as I said, taking into account your use case, choose. I wouldn't change code that is working and is not gonna be exposed (for example, if it is a global that is never taken as a parameter in functions) in any unsafe way.

但是正如我所说,考虑到您的用例,选择。我不会以任何不安全的方式更改正在运行和不会被公开的代码(例如,如果它是一个全局变量,在函数中从未被作为参数)。

#6


2  

I think std::array has many advantages over c-style arrays. So it is worthwhile to work to replace all occurrences or at least start using the std::array instead of c-style. For more information we can look here mentioned by C++11 FAQ by Bjarne Stroustrup.

我认为std::array比c风格的数组有很多优点。因此,有必要替换所有出现的情况,或者至少开始使用std::array而不是c样式。要了解更多信息,我们可以参考Bjarne Stroustrup在这里提到的c++ 11 FAQ。

  • It has no space overheads beyond what it needs to hold its elements.
  • 它没有多余的空间来容纳它的元素。
  • It does not use free store,and it can be initialized with an initializer list
  • 它不使用free store,并且可以使用初始化列表初始化它
  • It knows its size (number of elements).
  • 它知道它的大小(元素的数量)。
  • It doesn't convert to a pointer unless you explicitly ask it to.
  • 它不会转换为指针,除非你明确地要求它。
  • standard array's features makes it attractive for embedded systems programming (and similar constrained, performance-critical, or safety critical tasks) .
  • 标准数组的特性使得它对嵌入式系统编程(以及类似的受限、性能关键或安全关键任务)具有吸引力。

In other words, it is very much like a built-in array without the problems.

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

Regarding your point to table.size() is known, but it is valid only if somebody use the array in the context where it has been defined. If we need to pass it to some other function, then it is not known and we had to pass it.

关于表的点。size()是已知的,但是只有当某人在定义数组的上下文中使用数组时才有效。如果我们需要将它传递给其他函数,那么它是未知的,我们必须传递它。

#7


1  

There is a bunch of things:

有很多东西:

  • member functions so it looks like every other sequence in the standard library
  • 成员函数,所以它看起来像标准库中的其他序列
  • tuple like access (get, tuple_size, tuple_element) with compile time checked bounds access
  • 类似tuple的访问(get、tuple_size、tuple_element)具有编译时检查的边界访问
  • does not decay to a pointer
  • 它不会向指针衰减吗

The first point is pretty obvious and mainly a benefit in generic code. The second point is a little obscure: from a semantic arrayS are nothing else but degenerate tupleS (of course tupleS do not guarantee sequential storage in memory). Treating them as such makes sense and code working on tuples can work largely with arrays as well. The third point is a nice bonus and adds a little safety to code.

第一点很明显,主要是对通用代码的好处。第二点有点模糊:从语义数组中除了退化元组之外什么都不是(当然元组不保证在内存中进行顺序存储)。这样处理它们是有意义的,处理元组的代码在很大程度上也可以处理数组。第三点是一个不错的奖励,为代码增加了一点安全性。