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

master_dodo

我有一个很大的文件,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文件中占位符的值

无论我哪里有错,请纠正我。

Yan Zhou

就拿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,则无论如何,编译器都将被迫为该变量腾出空间。但最重要的是,通过在标头中声明此常量,而不是在外部源文件中定义常量,您不太可能会变得更糟。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章