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

问题描述 投票:1回答:3

我是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

c++ static initialization constants
3个回答
2
投票

有几种解决方案,取决于实际初始化的复杂程度,以及是否可以依赖C ++ 11。在所有情况下,解决方案取决于在加载代码以执行时对构造函数在静态变量上调用的事实。

在最简单的情况下,您只需使用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>


2
投票

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

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

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

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


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或更高版本。

© www.soinside.com 2019 - 2024. All rights reserved.