如何懒惰init一个全局变量?

时间:2016-12-15 09:46:53

标签: c++ const global lazy-initialization

我正在制作一个DLL。我希望在名称空间内为每个包含IBitmap的编译单元提供一个唯一的全局var(在我的例子中,是一个MyTools.h结构)。这是MyTools.h中的代码:

namespace MyTools
{
    const IBitmap BITMAP_CONTROL_BACKGROUND;
}

其中init为“空”var。我想初始化这个变量调用MyClass的一个方法(返回一个IBitmap)(稍后将实例化),但是当我在每个进程之前执行此操作时将使用此var:

BITMAP_CONTROL_BACKGROUND = myClass->LoadIBitmap(CONTROL_BACKGROUND, CONTROL_BACKGROUND_PATH, 1);

编译器告诉我BITMAP_CONTROL_BACKGROUND是const,所以我不能这样做。

以后启动并保持var全局的(最佳)方法是什么?

2 个答案:

答案 0 :(得分:1)

首先让我告诉你不要这样做。你正在使用一个全局变量(用另一个来初始化它......)然后就是Bad™。是的,您不希望在编译单元之间共享该变量,但这会使它更加奇怪(IMO)。

如果您仍在阅读并且我没有说服您不这样做,那么您可以使用函数初始化const表达式。将所有内容放在头文件中:

#pragma once

namespace MyTools {
    namespace Impl {
        IBitmap InitializeControlBackground();
    }

    const IBitmap BITMAP_CONTROL_BACKGROUND(Impl::InitializeControlBackground());
}

IBitmap MyTools::Imp::InitializeControlBackground() {
    return myClass->LoadIBitmap(CONTROL_BACKGROUND, CONTROL_BACKGROUND_PATH, 1);
}

很少注意到:

  • InitializeControlBackground()在嵌套的实现Impl命名空间中声明,不会污染MyTools命名空间。
  • 如果每个编译单元InitializeControlBackground()可能不同,则只需将其移至.cpp而不是.h。

答案 1 :(得分:1)

这里可以使用临时单例,但是你需要提供一个工厂对象来初始化实例。如果您可以随时创建myClass

// Header file.
namespace MyTools
{
    const IBitmap * bitmapControlBackground();
}

// Source file.
const IBitmap * MyTools::bitmapControlBackground()
{
    // Here is a casual singleton. If multi-thread access is possible,
    // here must be a casual way to solve it with mutex.
    static const IBitmap instance = MyClass().LoadBitmap(...);
    return &instance;
}

如果您有全局myClass变量:

// Source file.
const IBitmap * MyTools::bitmapControlBackground()
{
    // Here is a casual singleton. If multi-thread access is possible,
    // here must be a casual way to solve it with mutex.
    static const IBitmap instance = myClass->LoadBitmap(...);
    return &instance;
}

否则你必须在每次通话时传递它:

// Header file.
namespace MyTools
{
    const IBitmap * bitmapControlBackground(MyClass *creator);
}

// Source file.
const IBitmap * MyTools::bitmapControlBackground(MyClass *creator)
{
    // Here is a casual singleton. If multi-thread access is possible,
    // here must be a casual way to solve it with mutex.
    static const IBitmap instance = creator->LoadBitmap(...);
    return &instance;
}