我正在寻找用户使用非常复杂的初始条件进行模拟。我正在编写class A
,其成员变量需要由用户初始化,然后才能运行A.Solve()
以将结果存储在文件中。初始化相当复杂,需要在初始化后不再需要的几个临时数据结构。所以,我编写了另一个名为class Initializer
的类,它存储了对class A
对象的引用。我的代码看起来像这样:
class A {
friend class Initializer;
private:
// member variables storing the state of the system
public:
void Solve();
...
};
class Initializer {
private:
A& a
// Other data structures used in the initialization
...
public:
// functions called by the user to set up for the initialization
...
Initialize(); // after this is called, a will be ready to solve
};
int main(...) {
A a;
Initializer init(a);
// call functions on init to initialize the system
...
init.Initialize();
a.Solve();
return 0;
}
但似乎init
中的数据结构将存在于整个程序的堆栈中。为了防止这种情况,可以这样做:
A a;
Initializer *init = new Initializer(a);
....
init.Initialize();
delete init;
a.Solve();
或者这看起来不必要,我应该只包含class A
中的所有内容吗?
答案 0 :(得分:1)
要回答您的原始思路,通常的解决方案是限制init
变量的范围:
A a;
{
Initializer init(a);
//...
} // init is destroyed as soon as the scope exits
a.Solve();
您的new/delete
变体非常脆弱,如果在new
和delete
之间抛出任何内容,则会泄漏内存。要解决这个问题,请使用智能指针:
A a;
std::unique_ptr<Initializer> init(new Initializer(a));
//...
init.reset();
a.Solve();
然而正如其他人所说的那样,这整个设计有点奇怪,而且可能有点过分。如果初始化真的那么复杂,你无法摆脱构造函数,那么你可能想要反过来做:而不是Initializer
采用参数A
并对其进行操作,你应该传递一个完全可以使用的Initializer
到A
的构造函数,它将复制整个Initializer
以保留数据的副本,或者只复制相关的位。然后,Initializer
可能会重命名为Config
或类似的内容。请注意现在如何重用Config/Initializer
对象来初始化多个A
对象,甚至可以在两个A
初始化之间进行修改。
不幸的是,很难用如此少的信息给你明确的建议。
注意:如果您使用C ++ 11,您可能会对std::initializer_list
感兴趣,它会启用新的大括号初始化语法。根据数据的复杂程度,它可能涉及比当前解决方案更多的工作,但最终会得到非常好的直观语法。
答案 1 :(得分:0)
在这里,使用另一个类进行初始化目的似乎有点矫枉过正。
只需在A类构造函数中初始化。 构造函数执行完成后,临时数据结构将自动释放。