既然我们有std :: array,那么C-style数组的用途是什么?

R. *_*des 85 c++ arrays initialization c++11

std::array远远优于C阵列.即使我想与遗留代码进行互操作,我也可以使用std::array::data().有什么理由我想要一个老派阵列吗?

Jam*_*nze 59

除非我错过了一些东西(我没有仔细遵循标准中最近的更改),C样式数组的大部分用法仍然存在. std::array允许静态初始化,但它仍然不会为您计算初​​始值设定项.并且因为之前C样式数组的唯一真正用途std::array是静态初始化表格,如下所示:

MyStruct const table[] =
{
    { something1, otherthing1 },
    //  ...
};
Run Code Online (Sandbox Code Playgroud)

使用常用beginend模板函数(在C++ 11中采用)来迭代它们.没有提到编译器根据初始化器的数量确定的大小.

编辑:我忘了另一件事:字符串文字仍然是C样式数组; 即与类型char[].我不认为任何人会因为我们的原因而排除使用字符串文字std::array.

  • 您可以编写一个可变参数函数模板来构造数组,而无需指定长度. (7认同)
  • 使用C++ 17类模板扣除自动扣除初始化器的数量.例如,"auto a = std :: array {1,2,3};" (2认同)

Pup*_*ppy 29

不,呃,直截了当地说.并且有30个字符.

当然,您需要实现C数组std::array,但这并不是用户想要C数组的真正原因.此外,不,std::array性能不比C数组低,并且具有边界检查访问的选项.最后,任何C++程序都依赖于标准库是完全合理的 - 这就是它的标准 - 如果你没有访问标准库,那么你的编译器是不符合标准的问题被标记为"C++",而不是"C++和那些非C++的东西错过了一半的规范,因为他们感觉不合适."

  • C++ 0x最终草案(文档N3092)§1.4.7"定义了两种实现:托管和独立.对于托管实现,此国际标准定义了可用库集.独立实现是执行可以执行的实现在没有操作系统的情况下进行,并且具有一组实现定义的库,其中包括某些语言支持库"...... STL不包含在独立编译器中的"语言支持"库中 (11认同)
  • 允许独立实现几乎将所有标准库遗漏,并且仍然符合要求.不过,我会对在独立的C++ 11实现中无法实现`std :: array`的编译器产生严重怀疑. (3认同)

Sum*_*ant 25

使用C维数组比使用多维数组更容易std::array.例如,

char c_arr[5][6][7];
Run Code Online (Sandbox Code Playgroud)

而不是

std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;
Run Code Online (Sandbox Code Playgroud)

此外,由于C数组的自动衰减属性,c_arr[i]在上面的示例中将衰减为指针,您只需将剩余的维度作为另外两个参数传递.我的观点是c_arr复制并不昂贵.但是,cpp_arr[i]复制起来会非常昂贵.

  • 一个简单的`template <typename T,int M,int N> using array2d = std :: array <std :: array <T,N>,M>;`应解决任何这些问题. (29认同)
  • 您的示例`c_arr`复制起来非常昂贵!您必须自己提供代码.它将衰减的指针比引用更接近于引用,你可以使用`std :: array`传递引用,如果这是你想要的. (6认同)
  • @MilesRout *技术上*,不应该是 `std::size_t` 而不是 `int` 吗?很抱歉吹毛求疵,但这将使它变得普遍。 (2认同)

Ric*_*y65 13

正如Sumant所说,使用内置C阵列比使用多维数组要容易得多std::array.

嵌套时,std::array可能会变得非常难以阅读并且不必要地冗长.

例如:

std::array<std::array<int, 3>, 3> arr1; 
Run Code Online (Sandbox Code Playgroud)

相比

char c_arr[3][3]; 
Run Code Online (Sandbox Code Playgroud)

另外,还要注意begin(),end()size()全部返回无意义的值,当你窝std::array.

出于这些原因,我已经创建了自己的固定大小的多维数组容器,array_2d并且array_3d.它们类似于std::array2维和3维的多维数组.它们比内置的多维数组更安全,性能更差.我没有包含尺寸大于3的多维数组的容器,因为它们并不常见.在C++ 0x中,可以制作支持任意数量维度的可变参数模板版本.

二维变体的一个例子:

//Create an array 3 x 5 (Notice the extra pair of braces) 

fsma::array_2d <double, 3, 5> my2darr = {{
    { 32.19, 47.29, 31.99, 19.11, 11.19},
    { 11.29, 22.49, 33.47, 17.29, 5.01 },
    { 41.97, 22.09, 9.76, 22.55, 6.22 }
}};
Run Code Online (Sandbox Code Playgroud)

完整文档可在此处获得:

http://fsma.googlecode.com/files/fsma.html

你可以在这里下载这个库:

http://fsma.googlecode.com/files/fsma.zip

  • 固定大小的C风格数组很容易,但如果你想改变尺寸,事情会变得复杂.例如,给定`arr [x] [y]`,您无法判断`arr`是否是数组数组,指针数组,指向数组的指针或指针指针; 所有实现都是合法的,具体取决于您的需求.可能大多数现实世界的多维数组用例需要在运行时确定大小. (4认同)
  • @steffen我几年前做过尝试.您可以在此处查看:https://code.google.com/p/fsma/source/browse/trunk/variadic_template_array.hpp.测试用例:https://code.google.com/p/fsma/source/browse/trunk/variadic_template_array_test.cpp.我相信它可以做得更好. (3认同)

cma*_*ter 5

C++中提供的C风格数组实际上比真正的C数组更不通用.不同之处在于,在C中,数组类型可以具有运行时大小.以下是有效的C代码,但既不能用C++ C风格的数组表示,也不能用C++ array<>类型表示:

void foo(int bar) {
    double tempArray[bar];
    //Do something with the bar elements in tempArray.
}
Run Code Online (Sandbox Code Playgroud)

在C++中,您必须在堆上分配临时数组:

void foo(int bar) {
    double* tempArray = new double[bar];
    //Do something with the bar elements behind tempArray.
    delete[] tempArray;
}
Run Code Online (Sandbox Code Playgroud)

这是无法实现的std::array<>,因为bar在编译时不知道,它需要在C++中使用C风格的数组或std::vector<>.


虽然第一个例子可以用C++相对容易地表达(尽管需要new[]delete[]),但如果没有以下内容,则无法在C++中实现以下功能std::vector<>:

void smoothImage(int width, int height, int (*pixels)[width]) {
    int (*copy)[width] = malloc(height*sizeof(*copy));
    memcpy(copy, pixels, height*sizeof(*copy));
    for(y = height; y--; ) {
        for(x = width; x--; ) {
            pixels[y][x] = //compute smoothed value based on data around copy[y][x]
        }
    }
    free(copy);
}
Run Code Online (Sandbox Code Playgroud)

关键是,指向行数组的指针int (*)[width]不能在C++中使用运行时宽度,这使得C++中的任何图像处理代码都比在C中复杂得多.图像处理示例的典型C++实现如下所示:

void smoothImage(int width, int height, int* pixels) {
    int* copy = new int[height*width];
    memcpy(copy, pixels, height*width*sizeof(*copy));
    for(y = height; y--; ) {
        for(x = width; x--; ) {
            pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
        }
    }
    delete[] copy;
}
Run Code Online (Sandbox Code Playgroud)

此代码与上面的C代码完全相同,但它需要在使用索引的任何地方手动执行索引计算.对于2D情况,这仍然是可行的(即使它有很多机会使索引计算错误).不过,它在3D情况下变得非常讨厌.

我喜欢用C++编写代码.但每当我需要操作多维数据时,我真的会问自己是否应该将代码的这一部分移到C.

  • 应该注意的是,至少Clang和GCC支持C++中的VLA. (7认同)