C++ 头文件中的声明和初始化过多

Too much declaration and initialization in header file C++

我有一个很大的 Constants.h 文件,其中声明并初始化了大约 200 个变量(主要是数组)。我正在使用命名空间。

方法一:

//Constants.h

#ifndef CONSTANTS_H_
#define CONSTANTS_H_

namespace LibConstants
{
    const int a = 12;
    const std::string theme[2]; = {"themeA", "themeB"};
    const int arr[2] = {1, 2};
    // and around 200 more declarations with initialization
}
#endif

这个 .h 文件在几乎每个 .cpp 文件中都是 #include,但每次只使用非常少的变量,例如 LibConstants::theme[0]

我的方法没问题,但是它不会分配不必要的内存吗? 我是否应该按照方法,只在 .h 文件中定义变量并在 .cpp 中初始化?

就像下面的代码: 方法二:

//Constants.h

#ifndef CONSTANTS_H_
#define CONSTANTS_H_

namespace LibConstants {

    std::string getMyTheme(int arg);
    std::string getMyThemeName(int arg);

    const int a;
    const std::string theme[2];
    const int arr[2];
    // and around 200 more declarations with initialisation
};
#endif

正在 cpp 文件中初始化

//Constants.cpp

#include LibConstants.h
using namespace LibConstants {
     std::string getMyTheme(int arg) {
         theme[2] = {"themeA", "themeB"};
         return theme[arg];
     }
     std::string getMyThemeName(int arg) {
         ...
     }
}

一样使用
//HelloWorld.cpp

#include Constants.h
int main() {
     //METHOD 1:
     std::string a = LibConstants::theme[0]; // arg=0 is dynamic and is being read from localStorage in my case. 
     //METHOD 2:
     std::string a = LibConstants::getMyTheme(0); //Here also arg=0 is dynamic.
     ...
}

在这里,除了在头文件中声明为const std::string st[2];的数组外,不会为不需要的变量分配不必要的内存。

这里"arg=0"是运行时间投入。如果某些变量不依赖于 运行 时间而仅依赖于编译时间,在这种情况下它会简单地替换相应 .cpp 文件中占位符的值,这有关系吗?

不对的地方请指正

std::string为例。考虑一下,

namespace Constants {
const std::string str = "A not very short string";
}

str是一个class类型,它有一个构造函数,它必须分配内存来存储它的内容(除非在它的实现中使用了short-string优化。即使在在这种情况下,它仅适用于 "short string")。它被声明为命名空间范围变量。所以程序必须在启动时构造这个变量。每个声明了这个变量的程序都需要分配内存,并初始化它的内容。这是您可能不想要的开销,具体取决于它对您的性能的影响程度。

另一方面,如果你有,

const std::string &str()
{
     const static std::string s = "A not very short string";

     return s;
}

现在,您有了一个静态局部变量。它将在函数的第一个入口处被初始化。而且它只会被初始化一次。如果从未调用 str,则根本不会对其进行初始化。

但是请注意,字符串文字 "A not very short string" 仍会占用一些内存。它在哪里以及如何存储是实现定义的。通常在数据段中,影响通常很小。

与 class 类型相反。最好在 header.

中定义基本类型,尤其是整数类型

例如,

namespace Constants {
constexpr int x = 10;
}

优化编译器很可能根本不会存储变量 x 及其内容 10。相反,无论在哪里使用 x,它都会被 10 代替,并且在某些情况下,编码到指令 op-code 中(所谓的立即操作数)。当然,这又是一个实现细节。并且所有编译器都不能依赖这种优化。如果你使用 x 的地址或其他 ODR,编译器将不得不为这个变量腾出空间。但最重要的是,在 header 中声明此常量的情况不太可能比在外部源文件中定义它更糟。