c ++ - java样式的静态常量初始化

时间:2014-05-23 13:33:57

标签: c++ static initialization constants

我是c ++的新手。我试图在c ++中创建一个静态常量容器。在java中,我们通常通过静态常量初始化来实现。对于例如

class ConstantDefinition {
  public static const List<String> stringList = new ArrayList<String>();
  static {
       stringList.add("foo");
       stringList.add("boo");
       ...blah
       }                       
} 

java的工作方式,我不需要调用特定的方法来完成初始化。一旦将类加载到JVM中,静态块就会被初始化。但是在c ++中,我们没有与java相同的类加载机制。 我想要的是拥有一个不可修改的容器的副本,我可以使用它而不必每次都创建类对象。我理解的一种方法是创建一个类(类似于我上面的java示例)并定义一个const静态容器。但我发现在C ++中编写这种代码很困难,因为我不能在不调用方法的情况下进行初始化。那么实现这一目标的最佳方法是什么?第二种方法可能是我定义头文件并在命名空间内初始化全局变量。如果我采用这种方法,那么每当我包含该头文件或者将使用相同的头文件时,它会创建不同的全局变量吗?

谢谢, RG

3 个答案:

答案 0 :(得分:2)

如果将此代码放在任何编译单元(可能是源文件)中

namespace {
    static struct Initialiser
    {
        Initialiser()
        {
            // ToDo - initialisation code here
        }
    } TheInitialiser;
}

然后,一旦加载了库/可执行文件,就会运行代码块(在调用main函数之前,如果有的话)。这个成语很常见。

外部namespace{}(称为匿名命名空间)阻止此代码被发送到链接器和其他编译单元。

答案 1 :(得分:2)

有几种解决方案,具体取决于复杂程度 实际的初始化是,你是否可以指望C ++ 11或 不。在所有情况下,解决方案取决于事实 当代码是在静态变量上调用构造函数 加载执行。

在最简单的情况下,您只需使用a定义变量 initialzier,例如:

在课堂上:

class ConstantDefinition
{
    static std::vector<std::string> const stringList;
    //  ...
};

(所有解决方案都是一样的。)

在源文件中:

std::vector<std::string> const ConstantDefinition::stringList{
    "foo",
    "boo",
    //  ...
}

但这仅适用于C ++ 11。早期版本的 C ++,您需要定义变量:

std::string const stringListInit[] =
{
    "foo",
    "boo",
    //  ...
};
std::vector<std::string> const ConstantDefinition::stringList(
    begin( stringListInit ), end( stringListInit ) );

您还需要功能beginend

template <typename T, size_t N>
T* begin( T (&array)[N} ) { return array; }
template <typename T, size_t N>
T* end( T (&array)[N] ) { return array + N; }

如果您没有C ++ 11(它们在标准中) 图书馆),无论如何你都会想要它们。

不要忘记在任何一个初始化列表中,您都可以 使用任意表达式进行初始化,包括 函数调用。

最后,如果你的初始化过于复杂,你可以 总是将其封装在一个函数中:

namespace {

std::vector<std::string> stringListInit()
{
    std::vector<std::string> results;
    results.push_back( "foo" );
    //  ...
    return results;
}
}

std::vector<std::string> const ConstantDefinition::stringList( stringListInit() );

不要过于担心创建一个数组 复制然后销毁; C ++允许调用NRVO, 这意味着编译器实际上可以“合并”本地 stringListInitConstantDefinition::stringList中的变量 std::vector<std::string>,所以只有一个 {{1}}实际构建了。

答案 2 :(得分:1)

在ConstantDefinition.hpp中:

#include <string>
#include <vector>

struct ConstantDefinition
{
    static const std::vector<std::string> string_array;
};

在ConstantDefinition.cpp中:

const std::vector<std::string> ConstantDefinition::string_array =
{
    "foo",
    "boo"
};

注意:需要C ++ 11或更高版本。