2

我正在创建一个大小为 100 的数组和向量并生成一个随机值并尝试将数组和向量保持为排序状态。这是我的相同代码

vector<int> myVector;
int arr[SIZE];
clock_t start, finish;
int random;
for(int i=0; i<SIZE;i++)
{
    myVector.push_back(0);
    arr[i] = 0;
}
    //testing for Array
start = clock(); 
for(int i=0; i<MAX;++i)
{
    random = getRandom(); //returns rand() % 100
    for(int j=0; j<SIZE;++j){
        if(random > arr[j])
        {
            for(int k = SIZE - 1; k > j ; --k)
            {
                arr[k] = arr[k-1];
            }
            arr[j] = random;
            break;
        }
    }
}
finish = clock();
cout << "Array Time " << finish - start << endl;

//Vector Processing
start = clock();
for(int i=0; i<MAX;++i)
{
    random = getRandom(); //returns rand() % 100
    for(int j=0; j<SIZE;++j){
        if(random > myVector[j])
        {
            for(int k = SIZE - 1; k > j ; --k)
            {
                myVector[k] = myVector[k-1];
            }
            myVector[j] = random;
            break;
        }
    }
}
finish = clock();
cout << "Vector Time " << finish - start << endl;

输出如下:

阵列时间:5

矢量时间:83

在这种情况下,与数组相比,我无法理解为什么向量这么慢?这是否与优先选择向量而不是数组的经验法则相矛盾。

请帮忙 !

4

3 回答 3

4

首先:编程中的许多经验法则不是关于获得几毫秒的性能,而是关于管理复杂性,从而避免错误。在这种情况下,它是关于执行范围检查,大多数向量实现在调试模式下执行,而数组不执行。它还与动态数组的内存管理有关 - vector 确实管理它本身的内存,而您必须在数组中手动​​执行它,从而冒着引入内存泄漏的风险(曾经忘记delete[]或使用过delete?我是你!)。它是关于易用性,例如调整向量的大小或在中间插入元素,这是手动管理数组的繁琐工作。
换句话说,性能测量永远不会与经验法则相矛盾,因为经验法则从不以性能为目标。性能测量只是不遵守编码指南的少数可能原因之一。

乍一看,我猜你还没有启用优化。向量性能损失的主要来源将是许多向量实现为调试构建启用的索引检查。那些不会在优化的构建中发挥作用,所以这应该是您首先关心的问题。经验法则:未启用优化的性能测量毫无意义

如果启用优化仍然显示出更好的阵列性能,那么还有另一个区别:

数组存储在堆栈中,因此编译器可以在编译时直接使用地址并计算地址偏移量,而向量元素存储在堆中,编译器必须取消引用存储在向量中的指针。我希望优化器取消引用指针一次并计算从该点开始的地址偏移量。尽管如此,与编译时计算的地址偏移量相比,性能损失可能会很小,特别是如果优化器可以稍微展开循环的话。这仍然不违背经验法则,因为您在这里将苹果与梨进行比较。经验法则说,

std::vector动态数组更喜欢,std::array固定数组更喜欢。

所以要么使用动态分配的数组(包括某种delete[],请)或将固定大小的数组与std::array. 在 C++14 中,您必须在游戏中考虑新的候选对象,即std::dynarrayC++14 VLA,不可调整大小的运行时长度数组,可与 C 的 VLA 相媲美。

更新: 正如评论中所指出的,优化器擅长识别没有副作用的代码,例如您从未读取过的数组操作。std::vector实现非常复杂,优化器通常不会看穿这几层间接并优化所有插入,因此与向量的一些时间相比,数组的时间为零。在循环之后读取数组内容将禁用这种粗鲁的优化。

于 2013-07-03T15:34:27.943 回答
-1

矢量类必须动态增长内存,这可能涉及不时复制整个内容。它还必须为许多操作调用内部函数——比如重新分配。它还可能具有边界检查等安全功能。

同时,您的数组是预先分配的,并且您的所有操作可能不会调用任何内部函数。

这是更多功能的间接费用。

谁说向量在所有情况下都应该比数组快?您的数组不需要增长,这是数组确实更快的特殊情况!

于 2013-07-03T15:42:12.910 回答
-3

因为数组是本机数据类型,而编译器可以直接从内存中对其进行操作,所以它们由编译后的 exec 在内部进行管理。

另一方面,你得到的向量更像是一个类,我读到的模板,它需要通过另一个头文件和库进行一些管理。

本质上,本机数据类型可以在不包括任何标题的情况下进行管理,这使得它们更容易从程序中操作,而无需使用外部代码。这使得向量时间的开销是程序需要查看代码并使用与向量数据类型相关的方法。

每次你需要向你的应用程序添加更多代码并从中进行操作时,它都会使你的应用程序性能下降

您可以在此处此处此处阅读有关它的信息

于 2013-07-03T15:24:13.907 回答