多次调用初始化函数时的最佳实践?

发布于 2024-10-03 16:25:09 字数 521 浏览 0 评论 0原文

这可能是一个主观问题,但我或多或少是在问这个问题,并希望人们分享他们的经验。 (因为这是我在 C++ 中缺少的最大的东西)

无论如何,假设我有一个初始化函数,它从堆中初始化数据结构:

void initialize() {
    initialized = true;
    pointer = new T;
}

现在当我调用初始化函数两次时,就会发生内存泄漏(正确的?)。所以我可以通过多种方式来防止这种情况:

  • 忽略调用(只需检查我是否已初始化,如果我不执行任何操作)
  • 抛出错误,
  • 自动“清理”代码,然后重新初始化该事物。

现在,通常什么是“最佳”方法,有助于保持我的代码将来易于管理?

编辑:感谢您迄今为止的回答。不过我想知道人们如何处理这个更通用的方式。 - 人们如何处理可以被忽略的“简单”错误。 (比如,调用同一个函数两次,但只有 1 次才有意义)。

This may be a subjective question, but I'm more or less asking it and hoping that people share their experiences. (As that is the biggest thing which I lack in C++)

Anyways, suppose I have -for some obscure reason- an initialize function that initializes a datastructure from the heap:

void initialize() {
    initialized = true;
    pointer = new T;
}

now When I would call the initialize function twice, an memory leak would happen (right?). So I can prevent this is multiple ways:

  • ignore the call (just check wether I am initialized, and if I am don't do anything)
  • Throw an error
  • automatically "cleanup" the code and then reinitialize the thing.

Now what is generally the "best" method, which helps keeping my code manegeable in the future?

EDIT: thank you for the answers so far. However I'd like to know how people handle this is a more generic way. - How do people handle "simple" errors which can be ignored. (like, calling the same function twice while only 1 time it makes sense).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

你对谁都笑 2024-10-10 16:25:09

您是唯一能够真正回答这个问题的人:您是否认为 initialize 函数最终可能被调用两次,或者这是否意味着您的程序遵循了意外的操作?执行流程 ?

  • 如果initialize函数可以被多次调用:只需通过测试分配是否已经发生来忽略该调用。
  • 如果 initialize 函数没有合理的理由被多次调用:我相信这将是一个很好的例外候选者。

需要明确的是,我不认为清理和重新生成是一个可行的选择(或者您应该认真考虑重命名该函数以反映这种行为)。

You're the only one who can truly answer the question : do you consider that the initialize function could eventually be called twice, or would this mean that your program followed an unexpected execution flow ?

  • If the initialize function can be called multiple times : just ignore the call by testing if the allocation has already taken place.
  • If the initialize function has no decent reason to be called several times : I believe that would be a good candidate for an exception.

Just to be clear, I don't believe cleanup and regenerate to be a viable option (or you should seriously consider renaming the function to reflect this behavior).

双手揣兜 2024-10-10 16:25:09

对于可能并不总是需要的昂贵数据结构的按需延迟初始化来说,这种模式并不罕见。 Singleton 就是一个例子,或者是满足这些条件的类数据成员的例子。

如果结构已经就位,我要做的就是跳过初始化代码。

void initialize() {
    if (!initialized)
    {
      initialized = true;
      pointer = new T;
    }
}

如果您的程序有多个线程,则必须包含锁定以使其线程安全。

This pattern is not unusual for on-demand or lazy initialization of costly data structures that might not always be needed. Singleton is one example, or for a class data member that meets those criteria.

What I would do is just skip the init code if the struct is already in place.

void initialize() {
    if (!initialized)
    {
      initialized = true;
      pointer = new T;
    }
}

If your program has multiple threads you would have to include locking to make this thread-safe.

分開簡單 2024-10-10 16:25:09

我会考虑使用 boost 或 STL 智能指针。

I'd look at using boost or STL smart pointers.

网名女生简单气质 2024-10-10 16:25:09

我认为答案完全取决于 T (以及此类的其他成员)。如果它们是轻量级的并且不存在重新创建新的副作用,那么一定要清理并重新创建(但使用智能指针)。另一方面,如果它们很重(例如网络连接或类似的东西),那么如果设置了布尔值,您应该简单地绕过...

您还应该调查 boost::Optional,这样您就可以不需要整体标志,并且对于应该存在的每个对象,您可以检查是否已实例化,然后根据需要进行实例化...(在第一遍中说,有些构造正常,但有些失败......)

I think the answer depends entirely on T (and other members of this class). If they are lightweight and there is no side-effect of re-creating a new one, then by all means cleanup and re-create (but use smart pointers). If on the other hand they are heavy (say a network connection or something like that), you should simply bypass if the boolean is set...

You should also investigate boost::optional, this way you don't need an overall flag, and for each object that should exist, you can check to see if instantiated and then instantiate as necessary... (say in the first pass, some construct okay, but some fail..)

溺渁∝ 2024-10-10 16:25:09

在构造函数之后设置数据成员的想法很常见,所以不用担心,您绝对不是第一个遇到此问题的人。

有两种典型的用例:

  • 按需/延迟实例化:如果您不确定是否会使用它并且创建成本高昂,那么最好不要在构造函数中初始化它
  • 缓存数据:缓存可能昂贵的操作的结果这样后续调用就不需要再次计算它

您处于“惰性”类别,在这种情况下,更简单的方法是使用标志或可为空值:

  • 标志+值组合:重用现有类而不进行堆分配,但是这需要默认构造
  • 智能指针:这绕过了默认构造问题,但以堆分配为代价。检查您需要的复制语义...
  • boost::Optional:类似于指针,但具有深层复制语义并且没有堆分配。但需要完全定义类型,因此依赖性更重。

我强烈推荐 boost::Optional 习惯用法,或者如果您希望提供依赖隔离,您可能会退回到像 std::unique_ptr 这样的智能指针。 code> (或 boost::scoped_ptr 如果您无权访问 C++0x 编译器)。

The idea of setting a data member later than the constructor is quite common, so don't worry you're definitely not the first one with this issue.

There are two typical use cases:

  • On demand / Lazy instantiation: if you're not sure it will be used and it's costly to create, then better NOT to initialize it in the constructor
  • Caching data: to cache the result of a potentially expensive operation so that subsequent calls need not compute it once again

You are in the "Lazy" category, in which case the simpler way is to use a flag or a nullable value:

  • flag + value combination: reuse of existing class without heap allocation, however this requires default construction
  • smart pointer: this bypass the default construction issue, at the cost of heap allocation. Check the copy semantics you need...
  • boost::optional<T>: similar to a pointer, but with deep copy semantics and no heap allocation. Requires the type to be fully defined though, so heavier on dependencies.

I would strongly recommend the boost::optional<T> idiom, or if you wish to provide dependency insulation you might fall back to a smart pointer like std::unique_ptr<T> (or boost::scoped_ptr<T> if you do not have access to a C++0x compiler).

残龙傲雪 2024-10-10 16:25:09

我认为这可能是可以应用 Singleton 模式的场景。

I think that this could be a scenario where the Singleton pattern could be applied.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文