何时优先选择for循环而不是std::transform或反之?

17

我希望了解何时更实用使用std::transform,何时传统的for循环更好。

这是我的for循环代码,我想将两个向量合并成一个复合型向量:

    vector<double> vAmplitude = this->amplitudeData(N);
    vector<double> vPhase = this->phaseData(N);
    vector<complex<double>,fftalloc<complex<double> > > vComplex(N);
    for (size_t i = 0; i < N; ++i)
    {
        vComplex[i] = std::polar(vAmplitude[i], vPhase[i]);
    }

这是我的 std::transform 代码

    vector<double> vAmplitude = this->amplitudeData(N);
    vector<double> vPhase = this->phaseData(N);
    vector<complex<double>,fftalloc<complex<double> > > vComplex;
    std::transform(
                begin(vPhase), end(vPhase), begin(vAmplitude),
                std::back_inserter(vComplex),
                [](double p, double a) { return std::polar(a, p); });

请注意,vComplex是没有指定大小分配的,所以我想知道分配发生的时间。此外,我不明白为什么在lambda表达式中,pa必须反转使用。


1
这让我想起了《Going Native》节目中的一集,Sean Parent在其中举了一些例子,说明何时应该优先选择C++标准库的算法而不是使用原始循环语法。 - Felix Glas
2个回答

17

支持使用标准算法的一个考虑因素是,它能为你的代码(和你自己)做好准备以应对C++17替代执行模型版本

借用JoachimPileborg的回答,假设你将代码编写为:

vector<complex<double>,fftalloc<complex<double> > > vComplex(N);
std::transform(
    begin(vAmplitude), end(vAmplitude), begin(vPhase),
    std::begin(vComplex),
    std::polar);

经过一段时间,你意识到这是你代码中的瓶颈,需要并行运行它。所以,在这种情况下,你只需要将std::execution::par{}作为第一个参数添加到std::transform中即可。在手写版本中,你的(符合标准的)并行选择已经消失了。


3

关于分配,这就是std::back_inserter的作用。

您也可以为目标向量vComplex设置大小,在std::transform调用中使用std::begin

vector<complex<double>,fftalloc<complex<double> > > vComplex(N);
std::transform(
            begin(vPhase), end(vPhase), begin(vAmplitude),
            std::begin(vComplex),
            [](double p, double a) { return std::polar(a, p); });

关于lambda中参数的反转,是因为你在std::transform调用中使用vPhase作为第一个容器。如果你改用vAmplitude,你可以只传递std::polar的指针:
std::transform(
            begin(vAmplitude), end(vAmplitude), begin(vPhase),
            std::begin(vComplex),
            std::polar);

最后关于何时调用std::transform,在大多数情况下这更多是个人喜好的问题。我个人更喜欢在尝试自己编写代码前使用标准算法函数


代码只有使用lambda函数才能编译并正常工作,仅使用std::polar无法编译。 - Matthias Pospiech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接