【问题标题】:Performance with clean code in mind, what is better考虑到干净代码的性能,什么更好
【发布时间】:2017-04-25 09:37:23
【问题描述】:

对于 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。

【问题讨论】:

  • 剖析一下看看:)
  • 使用vector.reserve。
  • 如果你想复制整个向量,你可以做std::vector&lt;double&gt; vecOut1 = vecIn;,图书馆会为你做所有的工作。包括预先分配足够的空间。
  • 这是示例代码,当然我想做的不仅仅是将一个向量复制到另一个向量中。
  • 添加真实示例,而不仅仅是部分

标签: c++ performance vector initialization range


【解决方案1】:

其实差不多。

你可以让编译器为你优化:

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 */;
}

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

【讨论】:

  • 我编辑了我的问题,更清楚地表明我不想进行矢量复制,但提供的代码是示例代码。
  • 我编辑了我的答案,但仍不清楚您希望如何执行您的操作以及您的计算有多复杂。
  • 我不同意不使用自动。将迭代器的整个类型写入复杂的数据结构是耗时的,不会使您的代码更具可读性,并且如果您更改底层数据结构,则需要重写
  • @EyalK。你说的对。我没有说永远“停止”使用 auto 。我认为本文描述了汽车的最佳和最差acodersjourney.com/2016/02/c-11-auto
【解决方案2】:

您的第一个循环需要.reserve() 以与第二个循环具有相同的性能数量级:

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

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

【讨论】:

    猜你喜欢
    • 2018-08-26
    • 1970-01-01
    • 1970-01-01
    • 2010-10-28
    • 2014-01-04
    • 2013-12-27
    • 2012-10-18
    • 2021-06-10
    • 1970-01-01
    相关资源
    最近更新 更多