在头文件中放入const
Putting a const in a header
从我正在阅读和测试的所有内容来看,没有办法(没有预处理器宏)在共享头文件中定义常量,并确保每个TU不为该常量创建自己的存储空间。
我可以这样做:
const int maxtt=888888;
与
完全相同 static const int maxtt=888888;
如果这个头是共享的,它将工作,但每个TU得到自己的maxtt
副本。我还可以这样做,以防止:
extern const int maxtt;
但是我不能在这里定义maxtt
;为避免链接器错误,必须在CPP中完成
我的理解正确吗?
由于变量是常量,因此每个TU获得自己的副本通常是无关紧要的。
在c++中,由于这个原因,命名空间范围内的常量隐式地为static
。通常,这使得代码比只有一个带有外部链接的实例更好,因为(如果变量实际上是一个常量表达式)该常量通常可以直接折叠到用法站点中,根本不需要存储。
所以除非你真的需要取常量的地址,或者类似的东西,你应该坚持使用静态版本。(正如您已经看到的,您可以通过添加extern
来强制外部链接。)另一个原因可能是动态初始化,并且只希望一个对初始化器的调用:
// header:
extern int const n;
// one implementation:
int const n = init_function_with_side_effects();
静态构造(头文件中的int const n = init();
)将导致在每个TU中调用该函数一次。
你写,
从我阅读和测试的所有内容来看,没有办法(没有预处理器宏)在共享头文件中定义常量,并确保每个TU不为该常量创建自己的存储。
幸福这就是s 的。
对于较小的整数值,您总是可以使用enum
。这样做的代价是,您不能传递enum
值的地址,因为它没有地址。它是纯值。
然而,为整型值节省空间是毫无意义的,因为它太小了。
那么,让我们考虑一个更大的事情,
struct BiggyThingy
{
unsigned char zeroes[1000000];
BiggyThingy(): zeroes() {}
};
现在我们如何在头文件中声明BiggyThingy
常量,并确保整个程序只有一个常量?
使用内联函数。
最简单的是:
inline BiggyThingy const& getBiggyThingy()
{
static BiggyThingy const theThingy;
return theThingy;
}
static BiggyThingy const& biggyThingy = getBiggyThingy();
如果您不希望在每个翻译单元中使用引用占用空间(如指针),则只需使用不使用简化符号的引用的函数。
使用模板常量技巧。下面是另一种提供常量的方法,利用模板的特殊规则:
template< class Dummy >
class BiggyThingyConstant_
{
public:
static BiggyThingy const value;
};
template< class Dummy >
BiggyThingy const BiggyThingyConstant_<Dummy>::value;
typedef BiggyThingyConstant_<void> BiggyThingyConstant;
template< class Dummy >
class BiggyThingyConstant_
{
public:
static BiggyThingy const value;
};
template< class Dummy >
BiggyThingy const BiggyThingyConstant_<Dummy>::value;
typedef BiggyThingyConstant_<void> BiggyThingyConstant;
可以像
那样访问foo( BiggyThingyConstant::value )
或者如果你想要更好的符号,你可以为每个翻译单元添加一个引用,就像内联函数解决方案一样。
免责声明:
未编译过的代码。
但是我想你们明白了。: -)
这段代码只有在应用任何需要常量地址的操作时才会在TU中生成一个常量。
static int maxtt = 888888;
int * pmaxtt = &maxtt; //address of constant requested.
这也可以工作,并避免链接器问题(尽管它会存储maxtt
在每个TU如果地址被请求):
constexpr int maxtt = 888888;
避免extern
结构,因为它无法优化。
如果您担心存储空间,请使用枚举:
enum { maxtt = 888888 };
枚举数是标量右值,因此不需要存储空间。&maxtt
是非法的
的确,你对语义的理解是正确的。
在实践中,每个转换单元可能无法获得该整数的存储副本。一个原因是编译器可能在引用该值时将其实现为字面量。链接器也可能足够聪明,如果发现该存储没有被引用,它会丢弃该存储。
编译器可能不能自由地为常量使用字面量。您可以获取对该整数的引用,或者获取指向该整数的指针。在这种情况下,您需要存储——甚至可能需要交叉编译和惟一性。如果您在每个编译单元中取const
符号的地址,您可能会发现它是不同的,因为每个对象将获得一个唯一的静态副本。
如果使用枚举,可能会遇到类似的问题;您的const int
具有存储空间,您可以获取该存储空间的地址。除非将枚举对象的地址存储在某个地方,否则不能获取该对象的地址
- 使用 fopen 打开 .pak 文件并使该文件应用于 const 无符号字符* (C++)
- 如何通过头文件中的函数初始化 const int 数组?
- C++ 在头文件或构造函数中初始化 const 类成员变量?
- 将文本文件读取为 const char* 有时有效,有时无效
- 如果在执行过程中替换二进制文件,"const"数组是否驻留在内存中?
- 静态const数据成员在另一个文件中定义
- YAML::LoadFile(std::string const&) 找不到文件 [ROS 中的 yaml-cpp]
- 我可以在类头文件中定义一个类的const静态实例吗
- 在标头文件中使用const
- C++ 中的文件处理错误 - 调用"std::basic_fstream<char, std::char_traits<char> >::open(const char[8],
- 错误:在"boost::文件系统::p ath::文件名() const() + "/""中与"运算符+"不匹配
- 包含多个源文件中包含的"const"的头文件
- 在头文件中声明全局 const 对象
- 默认情况下,const 变量是文件的本地变量
- 为什么在 cpp 文件中定义了非 int const 静态
- 在 MoSync 中将数据写入文件(将 MAUtil::String 转换为 const char*)
- 为什么我可以在多个包含const int的cpp文件中包含一个头文件,而不会出现编译器错误
- 头文件随附的 C++ 文件中的 const 函数
- 头文件中定义的Const float**
- 如何在头文件中定义const-static std::string