我开始研究CRTP成语,我注意到GCC有一个fdevirtualize
标志,它应该允许在可能的vtable调用转换为直接调用时进行转换。虽然CRTP可以与任何(C++兼容)编译器一起使用,但是如果我只想使用gcc进行开发,是否可以避免使用CRTP习惯用法离开gcc进行虚拟化过程,或者在可能的情况下最好使用它,以便使用静态多态性以避免虚函数调用?CRTP vs GCC中的虚拟化标志
2
A
回答
4
根据编译器是否嵌入你的东西,Devirtualization可能有用或不用。
请注意,CRTP通常用于实现mixin和模板方法模式,例如,像这样:
template <typename T, typename Derived>
class pointer_base {
const Derived& self() const { return static_cast<const Derived&>(*this); }
public:
T& operator *() const { return *self().get(); }
T* operator ->() const { return self().get(); }
};
template <typename T>
class smart_pointer : public pointer_base<T, smart_pointer<T>> {
public:
T* get() const;
};
和虚拟呼叫形式:在任何情况下
template <typename T>
class pointer_base {
protected:
~pointer_base() = default;
public:
virtual T* get() const = 0;
T& operator *() const { return *get(); }
T* operator ->() const { return get(); }
};
template <typename T>
class smart_pointer : public pointer_base<T> {
public:
T* get() const override;
};
用法
smart_pointer<int> p(new int);
*p = 42;
注意,可能有多个不同的智能指针类。在虚函数版本中,它们都来自相同的pointer_base。这意味着所有这些基础函数都有一个版本可以共享。如果是这种情况,虚拟化就无法工作。
如果有问题的内联函数到调用它只会工作,因为那么编译器可以将代码专注于特定的具体的智能指针类型。
当然,如果帮手很小,他们内联的几率很高。另一方面,您现在拥有一个客户端可以使用的pointer_base类。你可以从基地私人派生,但是你必须为每个派生类中要公开的所有成员添加声明。像pointers_base这样的类包含很多(我的情况是2,但实际上应该有一个布尔转换)小函数,这很烦人。但是,CRTP的语法混乱也是如此。我认为,这归结为一个品味问题。
当你只有一个大模板方法时,编译器不会内联它。在这种情况下,它不能虚拟化。但CRTP有其自身的缺点:无论您是否需要,该方法都会重复用于每个基本实例。这可能导致代码膨胀。
所以最终归结为模板VS虚函数通常的问题:与其相关的代码尺寸的增加,或虚拟调用的性能损失,他们竖起了内联屏障的专业代码。
相关问题
- 1. CRTP vs过载和最终
- 2. GCC优化标志
- 3. MVVM vs数据虚拟化
- 4. GCC优化标志问题
- 5. 隐形GCC优化标志?
- 6. GCC优化标志的顺序
- 7. '虚拟XYZ' VS 'XYZ虚拟' 方法
- 8. 虚拟机VS.中间件
- 9. 硬件虚拟化
- 10. 相同类中的虚拟方法vs非虚拟方法
- 11. Popup中的UI虚拟化
- 12. gcc汇编标志
- 13. GCC标志给SCons
- 14. gcc汇编标志
- 15. TreeView虚拟化
- 16. 虚拟化WrapPanel
- 17. 虚拟化treelistview?
- 18. 虚拟化NET框架
- 19. 将CRTP与虚拟继承结合使用
- 20. KVM虚拟化10gbe虚拟以太网
- 21. 虚拟化问题
- 22. 虚拟表单vs Ajax POST
- 23. 性状vs虚拟开销
- 24. Pytables vs虚拟内存
- 25. 口译VS编译器VS虚拟机
- 26. 静态鸭打字VS CRTP
- 27. 如何关闭gcc中的特定优化标志
- 28. GCC连接带有警告/优化标志的目标文件
- 29. 托管虚拟机中的I/O虚拟化
- 30. WPF ItemControl虚拟化
很好的解释,谢谢。 – Jepessen