外部常量指针的常量正确性

Const correctness for extern const pointers

本文关键字:常量 正确性 指针 外部      更新时间:2023-10-16

我正在尝试定义可以在cpp文件中使用的常量字符串,这样既不能修改数据,也不能修改指针。链接器抱怨如下:

main.obj:错误LNK2001:未解析的外部符号"char const*const g_someString"

样本代码:

//constants.h
extern const char * const g_someString;
//constants.cpp
const char * const g_someString = "Hello";
// main.cpp
int main()
{
    strcmp(g_someString, "Hello");
}

但是,当const char*const被替换为const char*const时,就不会发生这种情况。编译器(MSVC 2015)是否优化了constants.cpp中的g_someString定义?

之前

const char * const g_someString = "Hello";

您需要将其声明为extern(例如通过包含标头),因为默认情况下const命名空间级别的变量具有内部链接。


也就是说,您可以在标题中定义字符串。单独的编译为您提供了修改字符串的能力,而无需重新生成大量文件,但除此之外,IMHO这还为时过早。


要使标头中的字符串定义在形式上对于inline函数是安全的,如果需要的话,您需要字符串(或者至少是指针)具有extern链接。一种方法是利用"一个定义规则"中模板的特殊豁免。例如:

// Perhaps best generated by some code generation facility:
template< class Dummy >
struct Strings_
{
    static char const* const some_string;
    static char const* const some_other_string;
};
template< class Dummy >
char const* const Strings_<Dummy>::some_string = "Blah!";
template< class Dummy >
char const* const Strings_<Dummy>::some_string = "Oh, well.";
using Strings = Strings_<void>;

然后像一样使用

inline void foo() { cout << Strings::some_string << endl; }

这里,Strings::some_string指针在所有翻译单元中将是相同的。

另一种选择是在inline函数中定义字符串。然后您可以使用例如枚举来命名它们。

enum String_id { some_string, some_other_string };
inline
auto strings( String_id const id )
    -> char const*
{
    switch( id )
    {
    case some_string:          return "Blah!";
    case some_other_string:    return "Oh, well.";
    }
    assert( false );    // Should never get here.
}

使用类似

inline void foo() { cout << strings( some_string ) << endl; }

inline函数具有extern链接,因此在所有翻译单元中都是一样的。