2012-07-12 41 views
0

我已經使用std :: transform將一些值添加到列表中的現有值。下面的代碼工作正常,我只是想知道是否有可能在執行轉換時避免所有對複製構造函數的調用(請參閱程序的輸出)。如果我只是破解了代碼,並且使for循環顯式調用Base的+ =操作符,則不會執行任何複製構造,並且值更改的位置更有效。爲什麼std :: transform使用構造函數?

我可以使變換調用操作符+ = Base而不是拷貝構造嗎?我應該專注於increment<Type>嗎?

程序:

#include <iostream> 
#include<list> 
#include <algorithm> 
#include <iterator> 

template<class T> 
class Base; 

template<class T> 
std::ostream& operator << (std::ostream& os, const Base<T>& b); 

template<class T> 
class Base 
{ 
    private: 
     T b_; 
    public: 
     typedef T value_type; 

     Base() 
      : 
       b_() 
     { std::cout << "Base::def ctor" << std::endl; } 

     Base (const T& b) 
      : 
       b_(b) 
     { std::cout << "Base::implicit conversion ctor: " << b_ << std::endl; } 

     const T& value() 
     { 
      return b_; 
     } 

     const Base operator+(const Base& b) const 
     { 
      std::cout << "Base operator+ " << std::endl; 
      return Base(b_ + b.b_); 
     } 

     const Base& operator+=(const T& t) 
     { 
      b_ += t; 
      return *this; 
     } 

     friend std::ostream& operator<< <T> (std::ostream& os, const Base<T>& b); 
}; 

template<class T> 
std::ostream& operator<< (std::ostream& os, const Base<T>& b) 
{ 
    os << b.b_; 
    return os; 
} 

template<class Type> 
class increment 
{ 
    typedef typename Type::value_type T; 

    T initial_; 

    public: 

     increment() 
      : 
       initial_() 
     {}; 

     increment(const T& t) 
      : 
       initial_(t) 
     {} 

     T operator()() 
     { 
      return initial_++; 
     } 
}; 

template<class Container> 
void write(const Container& c) 
{ 
    std::cout << "WRITE: " << std::endl; 
    copy(c.begin(), c.end(), 
     std::ostream_iterator<typename Container::value_type > (std::cout, " ")); 
    std::cout << std::endl; 
    std::cout << "END WRITE" << std::endl; 
} 

using namespace std; 

int main(int argc, const char *argv[]) 
{ 
    typedef list<Base<int> > bList; 

    bList baseList(10); 

    cout << "GENERATE" << endl; 
    generate_n (baseList.begin(), 10, increment<Base<int> >(10)); 
    cout << "END GENERATE" << endl; 

    write(baseList); 

    // Let's add some integers to Base<int> 

    cout << "TRANSFORM: " << endl; 

    std::transform(baseList.begin(), baseList.end(), 
        baseList.begin(), 
        bind2nd(std::plus<Base<int> >(), 4)); 
    cout << "END TRANSFORM " << endl; 

    write(baseList); 

    // Hacking the code: 
    cout << "CODE HACKING: " << endl; 
    int counter = 4; 
    for (bList::iterator it = baseList.begin(); 
     it != baseList.end(); 
     ++it) 
    { 
     *it += counter; // Force the call of the operator+= 
     ++counter; 
    } 
    write (baseList); 
    cout << "END CODE HACKING" << endl; 

    return 0; 
} 
+2

'std :: for_each'帶有謂詞增量會更好,這裏是IMO。 – jrok 2012-07-12 14:33:59

+0

感謝您的提示,如果您將其寫作答案,我會接受它。 – tmaric 2012-07-12 14:37:44

+0

我只是留下評論,因爲我認爲它不能完全回答你的問題:'int counter = 4; std :: for_each(baseList.begin(),baseList.end(),[&counter](int&i){i + = counter ++;});'如果你想留在C++ 03中,我可能寫一個自定義的函子,並以這種方式稱之爲'plus_assign'或其他東西。我不認爲你可以用'std :: plus'強制對+ =進行調用。 – jrok 2012-07-12 14:42:19

回答

8

Base (const T& b)不是一個拷貝構造函數,它是Base<T>一個構造函數,接受const T&。拷貝構造函數通常會有簽名Base(const Base&)

這就是說,你的構造函數被調用每次你從int,你在你的除了運營商做創建一個新的Base<int>時間。

最後,std :: transform()使用輸出迭代器賦值操作符將函數的結果分配給輸出。如果您想完全避免複製,則應使用std::for_each以及std::bind2nd(std::mem_fun_ref(&Base<int>::operator +=), 4))。這將避免複製,因爲它會在引用上運行。

+0

我不認爲這個答案中的任何東西都能讓他跳過這個副本,不是嗎? – 2012-07-12 14:51:44

+0

@MooingDuck,是的,因爲它避免了使用'transform',它通過修改現有的對象來創建一個新的對象。 – 2012-07-12 15:38:20

+1

@JonathanWakely:當我發表評論時,第三段不存在:D _現在我可以+1。 – 2012-07-12 20:38:34

相關問題