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 中声明此常量的情况不太可能比在外部源文件中定义它更糟。
我有一个很大的 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 中声明此常量的情况不太可能比在外部源文件中定义它更糟。