【问题标题】:Can a loop be avoided in this case?在这种情况下可以避免循环吗?
【发布时间】:2014-11-28 22:26:12
【问题描述】:

我有一个vector<A>,A 有一个字段 A::foo。 我想创建一个向量,其中元素是前一个向量的“foo”。当然我可以遍历向量的元素,但是在 STL 或其他主要库中是否有直接实现?

【问题讨论】:

  • 你的意思是“前一个元素”吗?
  • 不,我的意思是如果 V 是我的原始向量,则新向量 W 的索引 i 处的元素等于 V[i].foo
  • 好的 - 也许你应该包含你的 for 循环版本以明确你想要做什么?
  • 你想要std::transform()
  • 在内部我假设 std::transform 将执行一个循环,但不是吗?

标签: c++


【解决方案1】:

这应该可行

vector<A> vA; // this is your vector<A>, assumed to contain some `A`'s
...
vector<Foo> vFoo; // here is where we extract the Foo's
std::transform(std::begin(vA), std::end(vA), std::back_inserter(vFoo), 
               [](const A& param){return param.foo});

【讨论】:

  • 谢谢大家的回答
【解决方案2】:

您可以从&lt;algorithm&gt; 使用std::transform

#include<algorithm>

std::vector<A> as;
// fill it
std::vector<A::foo_type> foos;
foos.resize(as.size());
std::transform(as.begin(), as.end(), foos.begin(), [](const &A) { return A.foo; });

【讨论】:

  • 我想补充一点,resize 将默认构造 foo 的所有元素,这可能会或可能不会导致可观察到的开销。
【解决方案3】:

您可以使用 std::transform,但在这种情况下,我认为基于范围的 for 循环更具可读性,并且至少应该与使用 STL 的算法一样高效。


编辑: 为了说明我的观点:

struct Foo {};

struct Bar {
    Foo foo;
};

int main() {
    vector<Bar> bars(10);
    vector<Foo> foos1, foos2, foos3;

    foos1.reserve(bars.size());
    for (const auto& e : bars) { // this will become 'for (e:bars)' in the future
        foos1.push_back(e.foo);
    }

    foos2.resize(bars.size());
    transform(bars.begin(), bars.end(), foos2.begin(), [](const Bar& bar) { return bar.foo; });

    foos3.reserve(bars.size());
    transform(bars.begin(), bars.end(), back_inserter(foos3), [](const Bar& bar){return bar.foo; });

}

在我看来,循环版本更容易阅读(但我承认这可能是个人喜好问题)。

不要误会我的意思,我真的很喜欢算法,但在这种非常简单的情况下,它们的句法开销并没有起到作用。


编辑2: 一些处理器有gather instruction 指令。看看一个典型的编译器是否会生成这些以及在什么条件下会很有趣。

【讨论】:

  • 在效率方面应该没有任何区别
  • 这就是我的假设(当然你必须测量)。根据您编写算法版本的准确程度,编译器绝对可以生成相同的代码,但实际上这并不一定意味着它会。使用算法会增加另一层抽象,编译器在特定情况下可能会或可能无法穿透。然而,编译器总是会为给定的功能生成最有效的代码,而与使用的语法无关,这是一个神话。
  • 一般来说是的。但是,STL(或者更好地称为标准库)的设计考虑到了零开销。因此,就渐近复杂度而言,您在大 O 表示法中肯定具有相同的常数。据我所知,即使是小实例,标准库中的算法也应该非常接近最优。
  • 就大 O 而言,您是完全正确的。然而,在实际硬件上运行时,具有相同复杂度的两种算法(理论上)仍然存在数量级差异。再说一次,我完全同意你的看法,我不希望有什么不同。我只是想说明可能存在差异。
猜你喜欢
  • 2023-03-06
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2020-04-18
  • 1970-01-01
  • 2020-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多