在我们的c++课程中,他们建议不要再在新项目中使用c++数组。据我所知,Stroustroup本人建议不要使用数组。但是否存在显著的性能差异?


当前回答

在c++ 11中使用普通数组的理由就更少了。

从最快到最慢,本质上有3种类型的数组,这取决于它们所具有的特性(当然,实现的质量可以使事情变得非常快,即使是列表中的情况3):

静态的,在编译时大小已知。——std::array<T, N> 动态的,运行时大小已知,从不调整大小。这里的典型优化是,如果数组可以直接分配到堆栈中。——不可用。也许在c++ 14之后,在c++ TS中使用dynarray。在C中有vla 动态的,可在运行时调整大小。——std::向量T > <

为1。常量静态数组,在c++ 11中使用std::array<T, N>。

为2。在运行时指定固定大小的数组,但这不会改变它们的大小,在c++ 14中有讨论,但它已经转移到技术规范,最终由c++ 14制成。

为3。std::vector<T>通常会在堆中请求内存。这可能会影响性能,不过可以使用std::vector<T, MyAlloc<T>>来使用自定义分配器改善这种情况。相对于T mytype[] = new mytype[n];你可以调整它的大小它不会像普通数组那样衰减为指针。

使用上面提到的标准库类型来避免数组退化为指针。如果使用相同的特性集,将节省调试时间,并且性能与普通数组完全相同。

其他回答

关于杜里的贡献和我自己的测量。

结论是整数数组比整数向量快(在我的例子中是5倍)。然而,对于更复杂/未对齐的数据,数组和向量的速度大致相同。

在c++ 11中使用普通数组的理由就更少了。

从最快到最慢,本质上有3种类型的数组,这取决于它们所具有的特性(当然,实现的质量可以使事情变得非常快,即使是列表中的情况3):

静态的,在编译时大小已知。——std::array<T, N> 动态的,运行时大小已知,从不调整大小。这里的典型优化是,如果数组可以直接分配到堆栈中。——不可用。也许在c++ 14之后,在c++ TS中使用dynarray。在C中有vla 动态的,可在运行时调整大小。——std::向量T > <

为1。常量静态数组,在c++ 11中使用std::array<T, N>。

为2。在运行时指定固定大小的数组,但这不会改变它们的大小,在c++ 14中有讨论,但它已经转移到技术规范,最终由c++ 14制成。

为3。std::vector<T>通常会在堆中请求内存。这可能会影响性能,不过可以使用std::vector<T, MyAlloc<T>>来使用自定义分配器改善这种情况。相对于T mytype[] = new mytype[n];你可以调整它的大小它不会像普通数组那样衰减为指针。

使用上面提到的标准库类型来避免数组退化为指针。如果使用相同的特性集,将节省调试时间,并且性能与普通数组完全相同。

如果不需要动态调整大小,则会有存储容量的内存开销(一个指针/size_t)。就是这样。

有时候数组确实比向量好。如果你总是在操纵别人 固定长度的对象集合,数组更好。考虑下面的代码片段:

int main() {
int v[3];
v[0]=1; v[1]=2;v[2]=3;
int sum;
int starttime=time(NULL);
cout << starttime << endl;
for (int i=0;i<50000;i++)
for (int j=0;j<10000;j++) {
X x(v);
sum+=x.first();
}
int endtime=time(NULL);
cout << endtime << endl;
cout << endtime - starttime << endl;

}

X的向量在哪里

class X {
vector<int> vec;
public:
X(const vector<int>& v) {vec = v;}
int first() { return vec[0];}
};

X的数组版本为:

class X {
int f[3];

public:
X(int a[]) {f[0]=a[0]; f[1]=a[1];f[2]=a[2];}
int first() { return f[0];}
};

数组版本的main()将更快,因为我们避免了 每次在内部循环中“new”的开销。

(此代码由我发布到comp.lang.c++)。

为微优化人员准备的序言

记住:

程序员浪费了大量的时间去思考或担心程序中非关键部分的速度,而当考虑到调试和维护时,这些提高效率的尝试实际上会产生强烈的负面影响。我们应该忘记小的效率,大约97%的时候:过早的优化是万恶之源。但我们不应该错过这关键的3%的机会。”

(感谢metamorphosis的完整引用)

不要使用C数组来代替向量(或任何东西),因为你认为它更快,因为它应该是低级别的。你可能错了。

使用默认的向量(或者根据需要使用安全的容器),然后如果你的分析器说这是一个问题,看看你是否可以优化它,要么使用更好的算法,要么改变容器。

话虽如此,我们可以回到最初的问题。

静态/动态数组?

c++数组类比低级C数组表现得更好,因为它们了解自己很多东西,并且可以回答C数组不能回答的问题。他们能够自己打扫卫生。更重要的是,它们通常是使用模板和/或内联编写的,这意味着在调试中出现的大量代码在发布版本中分解为很少或没有代码,这意味着它们与内置的不太安全的竞争没有区别。

总而言之,它分为两类:

动态数组

使用指向malloc-ed/new-ed数组的指针最多和std::vector版本一样快,但安全性要低得多(参见litb的帖子)。

所以使用std::vector。

静态数组

最好使用静态数组:

和std::array版本一样快 更不安全。

所以使用std::array。

未初始化的内存

有时,使用一个向量而不是一个原始缓冲区招致一个可见的成本,因为向量将在构造时初始化缓冲区,而它所取代的代码没有,正如bernie by在他的回答中所说。

如果是这种情况,那么您可以通过使用unique_ptr而不是vector来处理它,或者,如果这种情况在您的代码线中不是例外,实际上编写一个类buffer_owner,它将拥有该内存,并让您轻松安全地访问它,包括调整它的大小(使用realloc?)或任何您需要的奖励。