[英]CRTP vs overload and final
我經常使用CRTP從基類調用派生類函數。 它具有不會產生虛擬函數調用成本的好處,例如:
template< class Derived >
class Base
{
public:
void foo()
{
static_cast<Derived*>(this)->foo_impl(); // Non virtual derived class call
}
};
class Derived : public Base<Derived>
{
private:
void foo_impl()
{
// Do Stuff
}
};
C ++ 11引入了final
語言標識符,它將虛函數(或類)標記為final,告訴編譯器將不再進一步覆蓋該函數。
我的理解(來自Going Native 2013演示文稿)如果虛擬函數被標記為final
則編譯器可以優化代碼以消除虛函數調用的開銷。
Ergo在上面的示例中,可以刪除CRTP並且仍然避免虛函數調用的開銷,前提是派生類將虛函數標記為final
即:
class Base
{
public:
virtual void foo_impl() = 0;
void foo()
{
foo_impl(); // Non virtual derived class call
}
};
class Derived : public Base
{
public:
// function marked as final, no virtual function call overhead
virtual void foo_impl() final
{
// Do Stuff
}
};
如果是這種情況,是否有任何建議,哪種方法最好?
CRTP是否仍然是首選,因為它保證函數調用是非虛擬的,而基於final
優化不能依賴?
這取決於你如何傳遞實例。 考慮在一個翻譯單元:
Derived d;
foo( &d );
在另一個:
void foo( Base* b )
{
b->foo();
}
除LTO外,編譯器沒有機會刪除虛擬調用開銷。
如果是OTOH,你有:
void foo( Derived* d )
{
d->foo();
}
編譯器現在可以足夠聰明,可以優化vtable查找,因為它具有所有必要的信息。 不過,我認為這不是保證。 沒有最終,vtable查找仍然是必要的,因為d
可以指向從Derived
東西,它還有另一個foo_impl()
。
我的5點:
當類名已知時,最近的GCC優化虛函數。
此外,標准說如果類名已知,則可以內聯虛擬功能 - 例如,沒有虛擬分派。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.