在c++中使用C样式数组有什么合理的理由吗?

时间:2022-05-28 22:28:37

Between std::vector and std::array in TR1 and C++11, there are safe alternatives for both dynamic and fixed-size arrays which know their own length and don't exhibit horrible pointer/array duality.

在TR1和c++ 11中,在std: vector和std:::array之间,动态数组和固定大小的数组都有安全的替代方案,它们知道自己的长度,并且不显示可怕的指针/数组二元性。

So my question is, are there any circumstances in C++ when C arrays must be used (other than calling C library code), or is it reasonable to "ban" them altogether?

因此,我的问题是,在c++中,当C数组必须使用时(除了调用C库代码),或者是否有理由“禁止”它们?

EDIT:

编辑:

Thanks for the responses everybody, but it turns out this question is a duplicate of

谢谢大家的回答,但这个问题其实是重复的

Now that we have std::array what uses are left for C-style arrays?

现在我们有了std::array c风格的数组还有什么用呢?

so I'll direct everybody to look there instead.

所以我要让每个人都看一下。

[I'm not sure how to close my own question, but if a moderator (or a few more people with votes) wander past, please feel free to mark this as a dup and delete this sentence.]

[我不知道如何结束我自己的问题,但是如果一个主持人(或者几个有投票的人)走过,请把这个标记为dup并删除这个句子。]

7 个解决方案

#1


2  

I didnt want to answer this at first, but Im already getting worried that this question is going to be swamped with C programmers, or people who write C++ as object oriented C.

我一开始并不想回答这个问题,但我已经开始担心这个问题会被C程序员所淹没,或者有人把c++写成面向对象的C。

The real answer is that in idiomatic C++ there is almost never ever a reason to use a C style array. Even when using a C style code base, I usually use vectors. How is that possible, you say? Well, if you have a vector v and a C style function requires a pointer to be passed in, you can pass &v[0] (or better yet, v.data() which is the same thing).

真正的答案是,在惯用的c++中,几乎从来没有理由使用C样式的数组。即使使用C样式的代码库,我通常也使用向量。你说这怎么可能?如果你有一个向量v和一个C样式的函数需要一个指针来传递,你可以传递&v[0](或者更好的是,v.data(),这是一回事)。

Even for performance, its very rare that you can make a case for a C style array. A std::vector does involve a double indirection but I believe this is generally optimized away. If you dont trust the compiler (which is almost always a terrible move), then you can always use the same technique as above with v.data() to grab a pointer for your tight loop. For std::array, I believe the wrapper is even thinner.

即使对于性能来说,也很少有C风格数组的情况。向量确实包含双重间接,但我相信这通常是被优化掉的。如果您不相信编译器(这几乎总是一个糟糕的步骤),那么您可以始终使用与上面的vdata()相同的技术来为您的紧密循环获取指针。对于std::array,我认为包装器更薄。

You should only use one if you are an awesome programmer and you know exactly why you are doing it, or if an awesome programmer looks at your problem and tells you to. If you arent awesome and you are using C style arrays, the chances are high (but not 100%) that you are making a mistake,

如果你是一个很棒的程序员,你知道你为什么要这么做,或者如果一个很棒的程序员看到你的问题并告诉你,你应该只使用一个。如果你不是很优秀,而且你正在使用C风格的数组,那么你犯错误的可能性很大(但不是100%),

#2


2  

Foo data[] = {

is a pretty common pattern. Elements can be added to it easily, and the size of the data array grows based on the elements added.

是一种很常见的模式。元素可以很容易地添加到其中,并且根据添加的元素,数据数组的大小会增加。

With C++11 you can replicate this with a std::array:

使用c++ 11,您可以使用std::array::

template<class T, class... Args>
auto make_array( Args&&... args )
-> std::array< T, sizeof...(Args) >
{
  return { std::forward<Args>(args)... };
}

but even this isn't as good as one might like, as it does not support nested brackets like a C array does.

但是,即使这样也不像人们希望的那样好,因为它不像C数组那样支持嵌套的方括号。

Suppose Foo was struct Foo { int x; double y; };. Then with C style arrays we can:

假设Foo是struct Foo {int x;双y;};。那么使用C风格的数组,我们可以:

Foo arr[] = {
  {1,2.2},
  {3,4.5},
};

meanwhile

与此同时

auto arr = make_array<Foo>(
  {1,2.2},
  {3,4.5}
};

does not compile. You'd have to repeat Foo for each line:

没有编译。你必须对每一行重复Foo:

auto arr = make_array<Foo>(
  Foo{1,2.2},
  Foo{3,4.5}
};

which is copy-paste noise that can get in the way of the code being expressive.

这是复制粘贴噪声,它会妨碍代码的表达。

Finally, note that "hello" is a const array of size 6. Code needs to know how to consume C-style arrays.

最后,注意“hello”是一个大小为6的const数组。代码需要知道如何使用c样式的数组。

My typical response to this situation is to convert C-style arrays and C++ std::arrays into array_views, a range that consists of two pointers, and operate on them. This means I do not care if I was fed an array based on C or C++ syntax: I just care I was fed a packed sequence of data elements. These can also consume std::dynarrays and std::vectors with little work.

我对这种情况的典型反应是将C风格的数组和c++ std:::数组转换为array_views,一个由两个指针组成的范围,并对它们进行操作。这意味着我不关心我是否被输入了一个基于C或c++语法的数组:我只关心我被输入了一系列数据元素。这些也可以消耗std::dynarrays和std::向量,几乎没有工作。

It did require writing an array_view, or stealing one from boost, or waiting for it to be added to the standard.

它确实需要编写一个array_view,或者从boost中窃取一个视图,或者等待它被添加到标准中。

#3


1  

Sometimes an exsisting code base can force you to use them

有时,一个现有的代码库会迫使您使用它们

#4


0  

The last time I needed to use them in new code was when I was doing embedded work and the standard library just didn't have an implementation of std::vector or std::array. In some older code bases you have to use arrays because of design decisions made by the previous developers.

上一次我需要在新代码中使用它们是在我做嵌入式工作时,而标准库只是没有std: vector或std::array的实现。在一些较早的代码库中,由于以前的开发人员所做的设计决策,您必须使用数组。

In most cases if you are starting a new project with C++11 the old C style arrays are a fairly poor choice. This is because relative to std::array they are difficult to get correct and this difficulty is a direct expense when developing. This C++ FAQ entry sums up my thoughts on the matter fairly well: http://www.parashift.com/c++-faq/arrays-are-evil.html

在大多数情况下,如果您正在使用c++ 11启动一个新项目,那么旧的C样式数组是一个相当糟糕的选择。这是因为相对于std:::array,它们很难得到正确,这是开发时的直接费用。这个c++ FAQ条目很好地总结了我对这个问题的看法:http://www.parashift.com/c+ -faq/ arrays--evil.html

#5


0  

Pre-C++14: In some (rare) cases, the missing initialization of types like int can improve the execution speed notably. Especially if some algorithm needs many short-lived arrays during his execution and the machine has not enough memory for pre-allocating making sense and/or the sizes could not be known first

pre - c++ 14:在某些(罕见的)情况下,缺少int等类型的初始化可以显著提高执行速度。特别是当某些算法在执行过程中需要许多短期数组时,并且机器没有足够的内存来进行有意义的预分配时,并且/或大小首先不能被知道

#6


0  

C-style arrays are very useful in embedded system where memory is constrained (and severely limited).

c型数组在内存受限的嵌入式系统中非常有用。

The arrays allow for programming without dynamic memory allocation. Dynamic memory allocation generates fragmented memory and at some point in run-time, the memory has to be defragmented. In safety critical systems, defragmentation cannot occur during the periods that have critical timing.

数组允许在没有动态内存分配的情况下进行编程。动态内存分配产生碎片化内存,在运行时的某个时刻,内存必须是碎片化的。在安全关键系统中,碎片整理不能在具有关键时间的期间发生。

The const arrays allow for data to be put into Read Only Memory or Flash memory, out of the precious RAM area. The data can be directly accessed and does not require any additional initialization time, as with std::vector or std::array.

const数组允许将数据放在只读内存或闪存中,而不是在宝贵的RAM区域中。数据可以直接访问,不需要任何额外的初始化时间,如std::vector或std::array。

The C-style array is a convenient tool to place raw data into a program. For example, bitmap data for images or fonts. In smaller embedded systems with no hard drives or flash drives, the data must directly accessed. C-style arrays allow for this.

c样式的数组是将原始数据放入程序的方便工具。例如,图像或字体的位图数据。在没有硬盘或闪存驱动器的小型嵌入式系统中,数据必须直接访问。c样式的数组允许这样做。

Edit 1:
Also, std::array cannot be used with compiler that don't support C++11 or afterwards.

编辑1:另外,std:::数组不能用于不支持c++ 11或以后的编译器。

Many companies do not want to switch compilers once a project has started. Also, they may need to keep the compiler version around for maintenance fixes, and when Agencies require the company to reproduce an issue with a specified software version of the product.

许多公司不希望在项目启动后就切换编译器。此外,他们可能需要保留编译器版本以进行维护修复,以及当代理机构要求公司重新生成产品的特定软件版本时。

#7


0  

Technically, you can rewrite C-style arrays with std::array or std::vector based on your usage.

从技术上讲,您可以根据使用情况使用std::array或std::vector重写c样式的数组。

However, std::array itself uses C-style arrays. std::array is declared by C-style arrays under the hood. Therefore, the existence of this array is somehow essential if we want avoid compiler magics.

但是,std::array本身使用c样式的数组。数组是由引擎盖下面的c样式数组声明的。因此,如果我们希望避免编译器魔法,那么这个数组的存在在某种程度上是必不可少的。

template <class T, int N>
class Array
{
    T data[N];
    .
    .

 

 

Sometimes writing a small code, I prefer old-school arrays rather than those classes. And if you OK with compiler extensions, you can take advantages of variable length nature of C-style arrays in your code. (Simplicity)

有时我编写一个小代码,我更喜欢老式数组而不是那些类。如果您对编译器扩展没有问题,那么您可以在代码中利用c样式数组的可变长度特性。(简单)

#1


2  

I didnt want to answer this at first, but Im already getting worried that this question is going to be swamped with C programmers, or people who write C++ as object oriented C.

我一开始并不想回答这个问题,但我已经开始担心这个问题会被C程序员所淹没,或者有人把c++写成面向对象的C。

The real answer is that in idiomatic C++ there is almost never ever a reason to use a C style array. Even when using a C style code base, I usually use vectors. How is that possible, you say? Well, if you have a vector v and a C style function requires a pointer to be passed in, you can pass &v[0] (or better yet, v.data() which is the same thing).

真正的答案是,在惯用的c++中,几乎从来没有理由使用C样式的数组。即使使用C样式的代码库,我通常也使用向量。你说这怎么可能?如果你有一个向量v和一个C样式的函数需要一个指针来传递,你可以传递&v[0](或者更好的是,v.data(),这是一回事)。

Even for performance, its very rare that you can make a case for a C style array. A std::vector does involve a double indirection but I believe this is generally optimized away. If you dont trust the compiler (which is almost always a terrible move), then you can always use the same technique as above with v.data() to grab a pointer for your tight loop. For std::array, I believe the wrapper is even thinner.

即使对于性能来说,也很少有C风格数组的情况。向量确实包含双重间接,但我相信这通常是被优化掉的。如果您不相信编译器(这几乎总是一个糟糕的步骤),那么您可以始终使用与上面的vdata()相同的技术来为您的紧密循环获取指针。对于std::array,我认为包装器更薄。

You should only use one if you are an awesome programmer and you know exactly why you are doing it, or if an awesome programmer looks at your problem and tells you to. If you arent awesome and you are using C style arrays, the chances are high (but not 100%) that you are making a mistake,

如果你是一个很棒的程序员,你知道你为什么要这么做,或者如果一个很棒的程序员看到你的问题并告诉你,你应该只使用一个。如果你不是很优秀,而且你正在使用C风格的数组,那么你犯错误的可能性很大(但不是100%),

#2


2  

Foo data[] = {

is a pretty common pattern. Elements can be added to it easily, and the size of the data array grows based on the elements added.

是一种很常见的模式。元素可以很容易地添加到其中,并且根据添加的元素,数据数组的大小会增加。

With C++11 you can replicate this with a std::array:

使用c++ 11,您可以使用std::array::

template<class T, class... Args>
auto make_array( Args&&... args )
-> std::array< T, sizeof...(Args) >
{
  return { std::forward<Args>(args)... };
}

but even this isn't as good as one might like, as it does not support nested brackets like a C array does.

但是,即使这样也不像人们希望的那样好,因为它不像C数组那样支持嵌套的方括号。

Suppose Foo was struct Foo { int x; double y; };. Then with C style arrays we can:

假设Foo是struct Foo {int x;双y;};。那么使用C风格的数组,我们可以:

Foo arr[] = {
  {1,2.2},
  {3,4.5},
};

meanwhile

与此同时

auto arr = make_array<Foo>(
  {1,2.2},
  {3,4.5}
};

does not compile. You'd have to repeat Foo for each line:

没有编译。你必须对每一行重复Foo:

auto arr = make_array<Foo>(
  Foo{1,2.2},
  Foo{3,4.5}
};

which is copy-paste noise that can get in the way of the code being expressive.

这是复制粘贴噪声,它会妨碍代码的表达。

Finally, note that "hello" is a const array of size 6. Code needs to know how to consume C-style arrays.

最后,注意“hello”是一个大小为6的const数组。代码需要知道如何使用c样式的数组。

My typical response to this situation is to convert C-style arrays and C++ std::arrays into array_views, a range that consists of two pointers, and operate on them. This means I do not care if I was fed an array based on C or C++ syntax: I just care I was fed a packed sequence of data elements. These can also consume std::dynarrays and std::vectors with little work.

我对这种情况的典型反应是将C风格的数组和c++ std:::数组转换为array_views,一个由两个指针组成的范围,并对它们进行操作。这意味着我不关心我是否被输入了一个基于C或c++语法的数组:我只关心我被输入了一系列数据元素。这些也可以消耗std::dynarrays和std::向量,几乎没有工作。

It did require writing an array_view, or stealing one from boost, or waiting for it to be added to the standard.

它确实需要编写一个array_view,或者从boost中窃取一个视图,或者等待它被添加到标准中。

#3


1  

Sometimes an exsisting code base can force you to use them

有时,一个现有的代码库会迫使您使用它们

#4


0  

The last time I needed to use them in new code was when I was doing embedded work and the standard library just didn't have an implementation of std::vector or std::array. In some older code bases you have to use arrays because of design decisions made by the previous developers.

上一次我需要在新代码中使用它们是在我做嵌入式工作时,而标准库只是没有std: vector或std::array的实现。在一些较早的代码库中,由于以前的开发人员所做的设计决策,您必须使用数组。

In most cases if you are starting a new project with C++11 the old C style arrays are a fairly poor choice. This is because relative to std::array they are difficult to get correct and this difficulty is a direct expense when developing. This C++ FAQ entry sums up my thoughts on the matter fairly well: http://www.parashift.com/c++-faq/arrays-are-evil.html

在大多数情况下,如果您正在使用c++ 11启动一个新项目,那么旧的C样式数组是一个相当糟糕的选择。这是因为相对于std:::array,它们很难得到正确,这是开发时的直接费用。这个c++ FAQ条目很好地总结了我对这个问题的看法:http://www.parashift.com/c+ -faq/ arrays--evil.html

#5


0  

Pre-C++14: In some (rare) cases, the missing initialization of types like int can improve the execution speed notably. Especially if some algorithm needs many short-lived arrays during his execution and the machine has not enough memory for pre-allocating making sense and/or the sizes could not be known first

pre - c++ 14:在某些(罕见的)情况下,缺少int等类型的初始化可以显著提高执行速度。特别是当某些算法在执行过程中需要许多短期数组时,并且机器没有足够的内存来进行有意义的预分配时,并且/或大小首先不能被知道

#6


0  

C-style arrays are very useful in embedded system where memory is constrained (and severely limited).

c型数组在内存受限的嵌入式系统中非常有用。

The arrays allow for programming without dynamic memory allocation. Dynamic memory allocation generates fragmented memory and at some point in run-time, the memory has to be defragmented. In safety critical systems, defragmentation cannot occur during the periods that have critical timing.

数组允许在没有动态内存分配的情况下进行编程。动态内存分配产生碎片化内存,在运行时的某个时刻,内存必须是碎片化的。在安全关键系统中,碎片整理不能在具有关键时间的期间发生。

The const arrays allow for data to be put into Read Only Memory or Flash memory, out of the precious RAM area. The data can be directly accessed and does not require any additional initialization time, as with std::vector or std::array.

const数组允许将数据放在只读内存或闪存中,而不是在宝贵的RAM区域中。数据可以直接访问,不需要任何额外的初始化时间,如std::vector或std::array。

The C-style array is a convenient tool to place raw data into a program. For example, bitmap data for images or fonts. In smaller embedded systems with no hard drives or flash drives, the data must directly accessed. C-style arrays allow for this.

c样式的数组是将原始数据放入程序的方便工具。例如,图像或字体的位图数据。在没有硬盘或闪存驱动器的小型嵌入式系统中,数据必须直接访问。c样式的数组允许这样做。

Edit 1:
Also, std::array cannot be used with compiler that don't support C++11 or afterwards.

编辑1:另外,std:::数组不能用于不支持c++ 11或以后的编译器。

Many companies do not want to switch compilers once a project has started. Also, they may need to keep the compiler version around for maintenance fixes, and when Agencies require the company to reproduce an issue with a specified software version of the product.

许多公司不希望在项目启动后就切换编译器。此外,他们可能需要保留编译器版本以进行维护修复,以及当代理机构要求公司重新生成产品的特定软件版本时。

#7


0  

Technically, you can rewrite C-style arrays with std::array or std::vector based on your usage.

从技术上讲,您可以根据使用情况使用std::array或std::vector重写c样式的数组。

However, std::array itself uses C-style arrays. std::array is declared by C-style arrays under the hood. Therefore, the existence of this array is somehow essential if we want avoid compiler magics.

但是,std::array本身使用c样式的数组。数组是由引擎盖下面的c样式数组声明的。因此,如果我们希望避免编译器魔法,那么这个数组的存在在某种程度上是必不可少的。

template <class T, int N>
class Array
{
    T data[N];
    .
    .

 

 

Sometimes writing a small code, I prefer old-school arrays rather than those classes. And if you OK with compiler extensions, you can take advantages of variable length nature of C-style arrays in your code. (Simplicity)

有时我编写一个小代码,我更喜欢老式数组而不是那些类。如果您对编译器扩展没有问题,那么您可以在代码中利用c样式数组的可变长度特性。(简单)