2017-03-09 95 views
1

我遇到了關於特質的Alexandrescu教程,我有一些反思分享。這是代碼:性狀vs虛擬開銷

// Example 6: Reference counting traits 
// 
template <class T> 
class RefCountingTraits 
{ 
    static void Refer(T* p) 
    { 
    p->IncRef(); // assume RefCounted interface 
    } 

    static void Unrefer(T* p) 
    { 
    p->DecRef(); // assume RefCounted interface 
    } 
}; 

template <> 
class RefCountingTraits<Widget> 
{ 
    static void Refer(Widget* p) 
    { 
    p->AddReference(); // use Widget interface 
    } 
    static void Unrefer(Widget* p) 
    { 
    // use Widget interface 
    if (p->RemoveReference() == 0) 
     delete p; 
    } 
}; 

與標準的虛擬功能成員案例相比,在這種情況下我們有多少開銷?在這種情況下我們也不直接訪問對象:我們仍然在傳遞一個指針。編譯器是否能夠以相同的方式優化它?

回答

1

在典型的生產優化級別(-O2/O2)中,您可以預期所顯示的所有代碼都是內聯的,並且沒有副作用的位可以優化。這留下了實際呼叫IncRefAddReference和檢查和delete -ion。

如果virtual功能已被使用,如果引用計數代碼是微不足道的(如不是線程安全的),這可能是約一個數量級慢,由於調度表查找和亂線函數調用,但編譯器,精確優化設置,CPU,調用約定等會有所不同。

一如既往,您必須關心,配置文件和實驗。

+0

如果我理解的很好,那麼優化後的代碼就像直接調用p-> IncRef(),而不用指針複製權限?它似乎太多一個數量級。完全同意分析:) – user3770392

+0

*「...對?」*對。 *「太大一個數量級」* - 甚至相反,稱爲運行時開關選擇的虛擬函數與虛擬調度在[this benchmark]中給出了9.2倍的因子(http://stackoverflow.com/a/4801861/410767),但總是很好衡量和分享您自己的基準代碼/結果。在這種情況下,當需要線程安全時,'IncRef()'DecRef()'可能並不那麼無關緊要,因此額外虛擬調度的影響將是一個較小的因素。 –

+0

謝謝你的解釋:) – user3770392