簡體   English   中英

這個函數應該返回什么類型的對象?

[英]What type of object should this function return?

考慮這個課程:

class Widget
{
    Widget::Widget();
    bool initialize();
}

Widget具有以下特征:

  1. 必須調用initialize()才能完全構造
  2. initialize()可能會失敗
  3. initialize()很貴

鑒於此,我在工廠函數中封裝創建,它始終返回相同的Widget實例:

Widget* widget() {
    static auto w = new Widget;
    static auto initialized = false;

    if (!initialized) {
        if (!w->initialize()) {
            return nullptr;
        }
        initialized = true;
    }

    return w;
}

widget()的返回類型應該是什么?

特別是,我想以某種方式明確表示返回的Widget的生命周期將超過任何調用者,但不會引用內部實現。

  1. 返回一個原始指針並添加一條注釋,指出“返回的指針指向一個具有靜態存儲持續時間的對象,該對象在程序結束前不會被刪除”。 這很簡單,但不能自我記錄。
  2. 返回std::shared_ptr<Widget> 這是自我記錄的,但我不喜歡它會引入完全不必要的引用計數開銷。
  3. 使用自操作的自定義刪除函數返回std::unique_ptr<Widget> 如果調用者將其轉換為shared_ptr我認為這與#2具有相同的感知問題。

我投票支持:

boost::optional<Widget&> widget() {
    static Widget w; // no reason for this to be a pointer
    static bool initialized = false;

    if (!initialized) {
        if (!w.initialize()) {
            return boost::none;
        }
        initialized = true;
    }

    return w;
}

它清楚地表明調用者沒有以任何方式擁有Widget ,不必擔心調用者delete Widget ,並且可以清楚調用是否成功。

在這里做正確的事情不是原始指針嗎? 它已經表達了限制。 它可能會失敗(通過返回nullptr),並且由於它沒有對指針做出任何承諾,因此調用者無法安全地將其刪除。 你得到一個原始指針,你不能假設你被允許做出有關指向對象生命周期的任何陳述。

Herb Sutter在這種情況下的推薦(第4項http://herbsutter.com/2013/05/30/gotw-90-solution-factories/ )是返回optional

函數可能返回指針可能還有一個原因,即返回nullptr以指示無法生成對象。 通常,如果我們無法加載窗口小部件,最好拋出異常來報告錯誤。 但是,如果無法加載窗口小部件是正常操作並且不應該被視為錯誤,則返回一個可選項,並且如果不需要報告其他類型的錯誤,則可能使工廠無法通過返回空的可選項進行良好通信。

正如其他人所指出的,如果工廠只生產一件產品,那么工廠也許不是正確的術語。 這似乎是一個單身人士。

考慮到:

  • 我們將只創建一個Widget實例
  • 該實例將在第一次有人要求時構建(如果有的話)
  • 該實例將一直存在,直到程序結束,然后應該銷毀
  • 沒有人應該刪除該實例

我會嘗試這樣的事情:

class Widget {
public:
    static Widget& Instance() {
        static Widget w{};
        return w;
    }

private:
    Widget() {
        // Expensive construction
    }
    Widget(const Widget&) = delete; // avoid copy

};

為了使生命周期和所有權更清晰,我將使用Singleton模式的約定,並使您的函數成為Widget類上的靜態getInstance函數。

class Widget {
  bool initialize();
 public:
  static Widget* getInstance() {
    static Widget w;
    static bool initialized = false;

    if (!initialized) {
      if (!w.initialize()) {
         return nullptr;
      }
      initialized = true;
    }
    return &w;
  }
};

我認為原始指針返回類型記錄了調用者不應該獲得所有權的事實,它可能為null。

暫無
暫無

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

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