3

假设我有一个对象,其成员的构造成本很高,并且需要一个reset()将其重置为其初始状态的函数:

struct Example
{
    // option 1: efficient, but need to duplicate initialization logic of reset() 
    Example(int param) : expensive_member_(param), param_(param)
    {
    }
    /* option 2: less code, but initializes expensive_member_ twice
    Example(int param) : param_(param)
    { 
        reset();
    }*/

    void reset()
    {
         expensive_member_ = ClassWithExpensiveConstructor(param_);
    }

    ClassWithExpensiveConstructor expensive_member_;
    int param_;
}

是否有更好的方法/模式可以有效地将对象重置为其初始状态,而无需复制初始化程序列表和reset函数中的初始化逻辑?

编辑:如果没有实现我想要的通用方法,那也是这个问题的可接受结果!

4

3 回答 3

1

一个简单的解决方案是使用(智能或常规)指针,以便初始化成员(即指针)的成本变得更小,并且实际对象仅在调用时被初始化reset()

 struct Example
 {
    Example(int param) : param_(param)
    { 
        reset();
    }

    void reset()
    {
         p.reset(new ClassWithExpensiveConstructor(param_));
    }

    unique_ptr<ClassWithExpensiveConstructor> p;
    int param_;
}
于 2015-07-27T10:13:27.193 回答
1

如果ClassWithExpensiveConstructor是构造/重置昂贵的一类,则应该是优化操作的一类。

另一种选择是在const成员中保留初始值的副本,假设副本构造/分配并不昂贵。这将使用更多内存,但如果您碰巧调用Example::reset()了很多,则会提高性能。

struct Example
{
    Example(int param)
    : expensive_member_backup_(param)
    , expensive_member_(expensive_mamber_backup)
    , param_(param)
    {
    }

    void reset()
    {
         expensive_member_ = expensive_member_backup_;
    }

    const ClassWithExpensiveConstructor expensive_member_backup_;
    ClassWithExpensiveConstructor expensive_member_;
    int param_;
}
于 2015-07-27T09:24:28.260 回答
1

您可以创建ExpensiveMember一个指针,在这种情况下,您的选项 2 不会ExpensiveMember在构造函数中调用构造函数,Example除非您明确调用它:

struct Example
{
    Example(int param) : expensive_member_(), param_(param)
    { 
         reset();
    }

    ~Example() {
         delete expensive_member_;   // better use unique_ptr etc
    }

    // Also a copy constructor and assignment operator 
    // are needed to avoid memory problems such as double-delete.
    // Also, better use unique_ptr etc.
    // This answer does not use unique_ptr just to make the main idea more clear.

    void reset()
    {
         delete expensive_member_;   // better use unique_ptr etc
         expensive_member_ = new ClassWithExpensiveConstructor(param_);
    }

    ClassWithExpensiveConstructor* expensive_member_;  // better use unique_ptr etc
    int param_;
}
于 2015-07-27T10:10:16.570 回答