头文件C ++

时间:2016-12-12 21:27:40

标签: c++ header-files

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

方法1:

//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文件几乎在每个#include文件中都是.cpp,但每次只使用非常小的变量LibConstants::theme[0]

我的方式运行正常,但是它不必要地分配内存? 我应该遵循这个方法,只在.h文件中定义变量并在.cpp初始化吗?

如以下代码所示: 方法2:

//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文件中占位符的值?

如果我错了,请纠正我。

1 个答案:

答案 0 :(得分:2)

std::string为例。考虑,

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

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

另一方面,如果你有,

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

     return s;
}

现在,您有一个静态局部变量。它将在函数的第一个条目初始化。它只会被初始化一次。如果永远不会调用str,则根本不会对其进行初始化。

但请注意,字符串文字"A not very short string"仍会占用一些内存。存储的位置和方式是实现定义的。通常在数据段中,影响通常很小。

与班级类型相反。最好定义基本类型,尤其是标题中的整数类型。

例如,

namespace Constants {
constexpr int x = 10;
}

优化编译器很可能根本不存储变量x及其内容10。相反,在使用x的地方,它将被10替换,并且在某些情况下,被编码到指令操作码(所谓的立即操作数)中。当然,这又是一个实现细节。并且所有编译器都不能依赖这样的优化。如果您使用x的地址或其他ODR,编译器将被迫为此变量腾出空间。但最重要的是,通过在标题中声明此常量而不是在外部源文件中定义它,您将不太可能更糟糕。