考虑到干净代码的性能,哪个更好

时间:2017-04-25 09:37:24

标签: c++ performance vector initialization range

对于for循环的清洁,我喜欢基于范围的for循环。在for循环中我想填充一个我手头知道大小的向量,但我缺少一个索引值。我现在有两种方法可以做到这一点,声明一个向量并使用push_back添加元素或创建一个初始化向量(因为不需要分配,所以应该更快),计算索引并插入一个元素。

问题:一方面的性能缺点是什么?和/或是否有更好的实施方案。

在示例代码下面,真实代码包含相对较少数量的项目(大概可能少于10个),但它将通过此​​过程运行数百万次。

    //The vector as input for the for loop
    std::vector<double> vecIn = { 1, 2, 3, 4, 5 };

    //Adding values to vectors, vector size changes on each loop right?
    std::vector<double> vecOut1;
    //Loop through vector with range looping
    for (auto& val : vecIn) {
        vecOut1.push_back(val); //In reality val is some calculated value based on the input.
    }

    //Adding values to initialized vector, but need to calculate index.
    std::vector<double> vecOut2(vecIn.size());
    //Loop through vector with range looping
    for (auto& val : vecIn) {
        auto i = &val - &vecIn[0];
        vecOut2[i] = val;  //In reality val is some calculated value based on the input.
    }

我喜欢第一个短路的循环,但是担心性能明智会更糟。

当然我也可以在循环开始时声明一个索引并迭代它,但这似乎有点破坏了清洁的目的。

编辑:为了澄清,这是演示代码,我将一个矢量复制到另一个矢量。在实际程序中,处理输入向量并基于输入向量计算新值。需要将新值插入/附加到矢量输出。在实际代码中,输入甚至不是向量而是boost :: ublas :: matrix。

2 个答案:

答案 0 :(得分:4)

几乎是一样的。

您可以通过执行以下操作让编译器为您优化:

std::vector<double> vecOut1(vecIn.begin(), vecIn.end());

std::vector<double> vecOut1 = vecIn

通过执行此操作,您将vecIn复制到vecOut1。

另一个建议:你是否能告诉你在for循环中处理的类型,避免使用关键字auto,并指定类型。

编辑:由于OP问题不明确,这是一个新答案。

你的第一个方法很好。还有一些不错的选择。

如果您在插入元素之前知道vecOut2向量的大小,则可以更好地访问索引:

std::vector<double> vecOut2(vecIn.size());
for(int i = 0;i < vecOut2.size(); i++){
   vecOut2[i] = vecIn[i] + /* Your calculation */;
}

这实际上取决于您希望如何执行计算,以及计算是否为线性(如果您必须在索引之间跳转)。

答案 1 :(得分:1)

您的第一个循环需求是.reserve(),其播放速度与第二个相同:

std::vector<double> vecOut1;
vecOut1.reserve(vecIn.size());
for (auto& val : vecIn) 
    vecOut1.push_back(val); 

reserve预先分配所请求的元素而不更改向量size - 因此循环中不会重新分配。