2013-08-31 73 views
2

1)C++完美轉發

template<typename T, typename Arg> 
    shared_ptr<T> factory(Arg arg) 
    { 
    return shared_ptr<T>(new T(arg)); 
    } 

2)

template<typename T, typename Arg> 
    shared_ptr<T> factory(Arg& arg) 
    { 
    return shared_ptr<T>(new T(arg)); 
    } 

3)

template<typename T, typename Arg> 
    shared_ptr<T> factory(Arg const & arg) 
    { 
    return shared_ptr<T>(new T(arg)); 
    } 

*)爲什麼數3優選比1號和2號?

*)如果工廠(41)被調用,爲什麼調用右值?

*)#define BOOST_ASIO_MOVE_ARG(type)type & &。什麼是& &在這種情況下?

+1

你可能想查找* rvalue引用*。他們是做到這一點的「正確」方式,部分爲此目的引入了語言。它還解釋了'type &&'符號。 – templatetypedef

回答

1

*)爲什麼數字3優於數字1和數字2?

(1)如果Arg不可複製,則不起作用。 (2)將不允許您傳遞右值,如factory<int>(42);

請注意,這三個示例都不涉及完美轉發。我不確定你的問題的主題是指什麼。

*)如果factory(41)被調用,爲什麼調用右值?

我不確定我是否理解這個問題。根據定義,41是一個右值。

*)#限定BOOST_ASIO_MOVE_ARG(型)型& &。什麼是& &在這種情況下?

type&&rvalue referencetype

9

實際上,方法#3是而不是好於1和2.這一切都取決於T的構造函數。

一個有點標準的方法是使用右值參考,它是您提到的&&

所以,更好的工廠將是這樣的:(這是什麼完美轉發實際上是)

template<typename T, typename Arg> 
std::shared_ptr<T> factory(Arg && arg) 
{ 
    return std::shared_ptr<T>(new T (std::forward<Arg>(arg))); 
} 

由於參考倒塌C++,這個功能可以利用規則(和轉發)rvalue refences和左值引用,即如果你傳遞一個右值,它將忠實地將該右值轉發給T的構造函數,並且如果你給它一個左值,這兩種引用(Something & && arg)將會崩潰,並且左值引用將被轉發給底層構造函數。

我想我介紹了你的問題在這裏,但明確地回答,

  • #3是這裏的首選方法。即使在C++ 11之前,您可能也希望和&函數的重載。 const&版本更好,它實際上會接受臨時值,但如果您的基礎T類型具有接受非const ref的構造函數,那麼您將收到編譯錯誤,因爲const&未隱式轉換爲&
  • 因爲你不能把文字41的地址(這是不是100%,技術上是正確的,但我認爲這是確定這樣認爲左值和右值的。)
  • 它標誌着一個rvalue reference。你需要閱讀有關的信息;一個解釋不適合在這裏,已經有幾個偉大的只是谷歌搜索了!

UPDATE:作爲評價切向所提到的,使用make_shared可以比用只是 - new ED指針構建shared_ptr更好。通過將控制塊(其包括引用計數)與對象本身一起分配,這可以在訪問引用計數器和對象時提供更好的緩存局部性,並且還可以節省一個內存分配,從而可以實現更高的效率。即使該實現沒有任何優化,它也不會比上述版本差。因此儘可能使用std::make_shared!這就是你如何做到這一點:

template<typename T, typename Arg> 
std::shared_ptr<T> factory (Arg && arg) 
{ 
    return std::make_shared<T>(std::forward<Arg>(arg)); 
} 
+0

@SoapBox:不,該類型確實需要調用「forward」。看看這裏:http://ideone.com/2v6Ytz – yzt

+1

它是'std :: forward (arg)',你不需要爲它的參數形成一個參考。 – Potatoswatter

+0

@Patatoswatter:哦,對!因爲它消除了類型中的引用,對嗎? – yzt