既然存在std::list
,std::vector
那么有理由在 C++ 中使用传统的 C 数组,还是应该避免使用它们,就像malloc
?
11 回答
在std::array
可用的 C++11 中,答案是“是的,应该避免使用数组”。在 C++11 之前,您可能需要使用 C 数组在自动存储中(即在堆栈上)分配数组。
当然,尽管std::array
在 C++11 中,实际上仅适用于静态数据。C 风格的数组与 相比具有三个重要优点
std::vector
:
它们不需要动态分配。出于这个原因,在您可能有很多非常小的数组的情况下,首选 C 样式数组。说一个像 n 维点这样的东西:
template <typename T, int dims> class Point { T myData[dims]; // ... };
通常,人们可能会想象一个
dims
非常小(2 或 3)T
的内置类型 (double
),并且您最终可能会std::vector<Point>
拥有数百万个元素。您绝对不希望数百万个 3 double 的动态分配。支持静态初始化。这只是静态数据的问题,例如:
struct Data { int i; char const* s; }; Data const ourData[] = { { 1, "one" }, { 2, "two" }, // ... };
这通常比使用向量 (and
std::string
) 更可取,因为它避免了所有的初始化顺序问题;在执行任何实际代码之前,数据已预先加载。最后,与上述相关,编译器可以从初始化器中计算出数组的实际大小。您不必计算它们。
如果您可以访问 C++11,std::array
则可以解决前两个问题,并且在第一种情况下绝对应该优先使用 C 样式数组。但是,它没有解决第三个问题,并且让编译器根据初始化程序的数量来确定数组的维度仍然是首选 C 样式数组的正当理由。
永远不要说“从不”,但我同意他们的角色被 STL 的真实数据结构大大削弱了。
我还要说对象内部的封装应该尽量减少这样的选择的影响。如果数组是私有数据成员,您可以将其换入或换出,而不会影响您类的客户。
我曾在无法使用动态内存分配的安全关键系统上工作。内存必须始终在堆栈上。因此,在这种情况下,您将使用数组,因为大小在编译时是固定的。
array
inc++
为您提供固定大小的快速替代动态大小std::vector
和std::list
. std::array是c++11
. 它提供了 std 容器的好处,同时仍然提供了 C 样式数组的聚合类型语义。
因此,在需要的地方,c++11
我肯定会std::array
在向量上使用 。但我会避免在C++03
.
大多数情况下,不,我想不出使用原始数组的理由,比如说,vectors
。如果代码是新的。
如果您的库需要与需要数组和原始指针的代码兼容,您可能不得不求助于使用数组。
我知道很多人都指出 std::array 用于在堆栈上分配数组,而 std::vector 则用于堆。但似乎都不支持非本地对齐。如果您正在执行任何想要使用 SSE 或 VPX 指令的数字代码(因此分别需要 128 或 256 字节对齐),C 数组似乎仍然是您最好的选择。
我想说数组仍然有用,如果您要存储少量静态数据,为什么不呢。
std::vector
与我能想到的相比,数组(当然包装在需要时会自动管理其释放的东西中)的唯一优点是vector
不能传递其数据的所有权,除非您的编译器支持 C++11 并移动构造函数。
C 风格的数组是一种基本的数据结构,因此在某些情况下使用它会更好。然而,对于一般情况,使用更高级的数据结构来修整基础数据的角落。C++ 允许你用内存做一些非常有趣和有用的事情,其中许多都适用于简单的数组。
您应该在内部使用 STL 容器,但您不应该在不同模块之间传递指向此类容器的指针,否则您将陷入依赖地狱。例子:
std::string foo;
// fill foo with stuff
myExternalOutputProc(foo.c_str());
是一个很好的解决方案,但不是
std::string foo;
// fill foo with stuff
myExternalOutputProc(&foo);
原因是 std::string 可以以多种不同的方式实现,但 c 样式的字符串始终是 c 样式的字符串。