簡體   English   中英

boost::transform 與 std::transform

[英]boost::transform vs std::transform

從下面的代碼片段中,我是否應該得出結論, std::transformboost::transform更受青睞,因為前者使用的初始化和析構函數比后者少?

#include <algorithm>
#include <boost/range/algorithm.hpp>
class Ftor {
public:
    Ftor(const Ftor& rhs) : t(rhs.t)
    { std::cout << " Ftor : copy\n"; }
    Ftor(float rate) : t(rate)
    { std::cout << " Ftor : init\n"; }
    ~Ftor()
    { std::cout << "~Ftor : ...\n"; }
    float operator() (float x) { return x < t ? 0.0 : 1.0; }
private:
    float t;
};

typedef std::vector<float> vec_t;

int main (void) 
{
    vec_t arg(/*...*/);
    vec_t val(arg.size());
    float x = 1.0;
    /* Standard transform test */
    std::cout << "Standard transform:\n";
    std::transform(arg.begin(), arg.end(), val.begin(), Ftor(x));
    std::cout << "Boost transform:\n";
    /* Boost transform test */
    boost::transform(boost::make_iterator_range(arg.begin(), arg.end()),
                     val.begin(), Ftor(x));
}

輸出:

Standard transform:
 Ftor : init
~Ftor : ...
Boost transform:
 Ftor : init
 Ftor : copy
~Ftor : ...
~Ftor : ...

標准轉換使用 2 次調用。 Boost 變換使用 4 次調用。 標准變換獲勝。 還是……?

附錄

正如@sehe 建議的那樣, std::ref每次調用transform時都會保存一個構造函數,而boost::transform只使用一次調用。 但是std::ref不能將臨時參數作為參數。 但是,傳遞Ftor f(x)是可以的,因為后者有一個明確的地址。

在循環內調用 transform 時考慮構造函數/析構函數調用。 我現在有兩個 boost 選項:

std::cout << "with std::ref\n";
for (/*...*/) {
    x = ...;
    f = Ftor(x);
    boost::transform(arg, val.begin(), std::ref(f));
}

std::cout << "with temporary\n";
for (/*...*/) {
    x = ...;
    boost::transform(arg, val.begin(), Ftor(x));
}

輸出:

with std::ref
 Ftor : init
 Ftor : init
 ...
~Ftor : ...
with temporary
 Ftor : init
 Ftor : copy
~Ftor : ...
~Ftor : ...
 Ftor : init
 Ftor : copy
~Ftor : ...
~Ftor : ...
 ...

我有一個 gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 有或沒有-O3產生相同的結果。

構造函數/析構函數是否“昂貴”是相對於operator()而言的。 它是最終產品,將執行不太苛刻的數學運算,與上面的示例沒有什么不同。

coliru 的完整示例

允許 STL 算法復制它們的謂詞/函子。 這主要是因為它們是按值傳遞的。

您看到的是boost又進行了一次前向調用。

有問題嗎?

通常不會。 編譯器非常擅長內聯、復制省略和依賴分析。

很有可能,生成的代碼最終完全相同。

當然,添加cout語句會完全破壞它。 比較生成的代碼,沒有構造函數/析構函數的副作用破壞它!

使用無副作用的公平比較為 STL 和 Boost 變體生成相同的代碼:http: //paste.ubuntu.com/14544891/

使固定

STL(和 boost 算法)的設計方式,如果需要,您可以通過引用顯式傳遞仿函數。 您為此使用std::ref

生活在 Coliru

#include <algorithm>
#include <vector>
#include <iostream>
#include <functional>
#include <boost/range/algorithm.hpp>

class Ftor {
  public:
    Ftor(const Ftor &rhs) : t(rhs.t) { std::cout << " Ftor : copy" << std::endl; } 
    Ftor(float rate) : t(rate)       { std::cout << " Ftor : init" << std::endl; } 
    ~Ftor()                          { std::cout << "~Ftor : ..."  << std::endl; } 
    float operator()(float x)        { return x; }  

  private:
    float t;
};

typedef std::vector<float> vec_t;

int main(void) {
    vec_t arg(190, 1), val(arg.size());

    {
        std::cout << "STL transform: " << std::endl;
        Ftor f(1.0);
        std::transform(arg.begin(), arg.end(), val.begin(), std::ref(f));
    }
    std::cout << "-----\n";

    {
        std::cout << "Boost transform: " << std::endl;
        Ftor f(1.0);
        boost::transform(arg, val.begin(), std::ref(f));
    }
    std::cout << "-----\n";
}

印刷

STL transform: 
Ftor : init
~Ftor : ...
-----
Boost transform: 
Ftor : init
~Ftor : ...
-----

注意無論如何,在容器上使用范圍算法並構造范圍boost::make_iterator_range(arg.begin(), arg.end())而不是僅使用arg非常非常諷刺的:

boost::transform(arg, val.begin(), Ftor(x));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM