我应该使用Initialize-on-demand习语,如果是这样的话?

ein*_*ica 9 c++ idioms idiomatic

我有以下代码:

 MyType x = do_something_dangerous();
 // ...
 if (some_condition) {
     // ...
     bar(x);
 }
 else { 
     // ...
 }
 // ...
 if (another_condition_which_may_depend_on_previous_if_else} {
     // ...
     baz(x);
 }
Run Code Online (Sandbox Code Playgroud)

这个想法是,在某些情况下,我可能需要使用,这可能是事先确定的难度/不方便x.但是在我不需要使用它的情况下,尝试初始化它可能是不好的(比如说,可能会导致我的进程崩溃).

现在,似乎我需要使用的是一个初始化按需持有者(链接侧重于Java,所以这里是一个草图):某种Wrapper<MyType>Wrapper<MyType, do_something_dangerous>一种get()方法,这样第一次get()调用do_something_dangerous(),后来get()只是通过第一次通话获得的价值.

  • 这确实是一种合适的方法吗?
  • 是否有一些标准(ish)实现这个成语,或者它的一个变体?

笔记:

  • 我可以使用boost::optional,但这有点麻烦,也扭曲了预期的用途:"建议optional<T>在没有类型的价值,T缺乏的地方,只有一个,清楚(对所有各方)的原因使用价值与任何常规价值一样自然T."

Ser*_*sta 5

恕我直言,你提出的解决方案是完全合适的:

  • 实施它是微不足道的
  • 它完全满足您的需求

当然,如果你已经在你的应用程序中使用了boost,你可以查看建议的boost :: optional模块,但是我不确定它是否正是你想要的,因为当你需要的东西被推迟时,它更适合于可以为空的对象设计初始化.

我的建议是:坚持专用的包装器实现.

不像其他的答案,我想你应该使用一个单身,但单纯的喜欢(使用初始化参数实现)的东西:

template<typename T, typename I>
class LazyInit {
    T* val;
    I init;

public:
    LazyInit<T, I>(I init): init(init) {
        val = NULL;
    }
    ~LazyInit<T, I>() {
        delete val;
        val = NULL; // normally useless here
    }
    T& get() {
        if (val == NULL) {
            val = new T(init);
        }
        return *val;
    }
};
Run Code Online (Sandbox Code Playgroud)

这是一个使用初始化函数的实现:

template<typename T>
class LazyInit {
    T* val;
    T (*init)();

public:
    LazyInit<T>(T (*init)()): init(init) {
        val = NULL;
    }
    ~LazyInit<T>() {
        delete val;
        val = NULL; // normally useless here
    }
    T& get() {
        if (val == NULL) {
            val = new T(init());
        }
        return *val;
    }
};
...
LazyInit<MyType> x(do_something);
...
bar(x.get()); // initialization done only here
Run Code Online (Sandbox Code Playgroud)

您可以轻松地将两者结合起来,使用带参数的函数构建实现.