繁体   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