簡體   English   中英

GTP中的CRTP與devirtualization標志

[英]CRTP vs devirtualization flag in GCC

我開始研究CRTP習語,我注意到GCC有一個fdevirtualize標志,應該允許在可能的vtable調用直接調用時進行轉換。

雖然CRTP可以應用於任何(C ++兼容)編譯器,但如果我只想用gcc開發,我可以避免CRTP習慣用於將gcc作為虛擬化過程,或者在使用靜態多態性時最好使用它。為了避免虛函數調用?

Devirtualization可能有用與否,具體取決於編譯器是否內聯您的內容。

請注意,CRTP通常用於實現mixins和模板方法模式,例如:

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類。 您可以從基礎私有派生,但是您必須為每個派生類中要公開的所有成員添加聲明。 對於像pointer_base這樣的類,它包含很多(在我的情況下為2,但確實應該有一個布爾轉換)的小函數,這很煩人。 但是,CRTP的語法混亂也是如此。 我想,這歸結為品味問題。

當你只有一個大模板方法時,編譯器最不會內聯它。 在這種情況下,它無法虛擬化。 但CRTP有其自身的缺點:無論您是否需要,該方法都會在基礎的每個實例化中重復。 這可能會導致代碼膨脹。

因此,它最終歸結為模板與虛函數的常見問題:專用代碼及其相關代碼大小的增加,或虛擬調用的性能損失以及它們提出的內聯障礙。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM