这可能是一个主观问题,但我或多或少地要求它,并希望人们分享他们的经验。 (因为这是我在C ++中缺少的最重要的东西)
无论如何,假设我有一个不明确的理由 - 初始化函数从堆中初始化数据结构:
void initialize() {
initialized = true;
pointer = new T;
}
现在当我调用初始化函数两次时,会发生内存泄漏(对吗?)。所以我可以通过多种方式防止这种情况:
现在通常的“最佳”方法是什么,这有助于将我的代码保留在未来?
编辑:谢谢您的回答。但是,我想知道人们如何处理这是一种更通用的方式。 - 人们如何处理可以被忽略的“简单”错误。 (比如,调用相同的函数两次,而只有一次是有意义的。)
答案 0 :(得分:4)
你是唯一能够真正回答这个问题的人:你是否认为initialize
函数最终可以被调用两次,或者这是否意味着你的程序出现意外情况执行流程?
initialize
函数:只需通过测试是否已经进行分配来忽略该调用。initialize
函数没有合理的理由可以被多次调用:我相信这将是一个很好的候选例外。为了清楚起见,我不相信清理并重新生成是一个可行的选择(或者你应该认真考虑重命名函数以反映这种行为)。
答案 1 :(得分:2)
对于可能并不总是需要的昂贵数据结构的按需或延迟初始化,这种模式并不罕见。 Singleton是一个示例,或者是满足这些条件的类数据成员。
如果结构已经到位,我会做的就是跳过初始化代码。
void initialize() {
if (!initialized)
{
initialized = true;
pointer = new T;
}
}
如果你的程序有多个线程,你必须包含锁定才能使这个线程安全。
答案 2 :(得分:0)
我会考虑使用boost或STL智能指针。
答案 3 :(得分:0)
我认为答案完全取决于T
(以及本课程的其他成员)。如果它们是轻量级的并且没有重新创建新副本的副作用,那么一定要清理并重新创建(但使用智能指针)。另一方面,如果它们很重(比如网络连接或类似的东西),如果设置了布尔值,你应该绕过它...
您还应该调查boost::optional
,这样您就不需要整体标记,并且对于应该存在的每个对象,您可以检查是否实例化然后根据需要进行实例化...(比如说第一遍,有些构造没问题,但有些失败..)
答案 4 :(得分:0)
在构造函数之后设置数据成员的想法很常见,所以不要担心你肯定不是第一个遇到这个问题的人。
有两种典型的用例:
您处于“懒惰”类别,在这种情况下,更简单的方法是使用标志或可空值:
boost::optional<T>
:类似于指针,但具有深层复制语义且没有堆分配。要求类型完全定义,依赖性更重。我强烈推荐boost::optional<T>
成语,或者如果您希望提供依赖性绝缘,您可能会回到智能指针,如std::unique_ptr<T>
(或boost::scoped_ptr<T>
如果您没有访问权限到C ++ 0x编译器。)
答案 5 :(得分:-1)
我认为这可能是可以应用Singleton模式的情况。