简体   繁体   English

在C ++中定义常量C字符串的正确方法?

[英]Correct way to define a constant C-string in C++?

Most of the time I see constant C-strings defined as: 大多数时候我看到常量C字符串定义为:

static char const* MY_CONSTANT = "Hello World";

However, the pointer itself is not const . 但是, 指针本身不是const Wouldn't it be more appropriate to do it like below? 像下面这样做是不是更合适?

static char const* const MY_CONSTANT = "Hello World";

There are 2 goals with constant globals like this, I think: 我认为有两个像这样的常量全局变量的目标:

  1. Do not allow modification of the string 不允许修改字符串
  2. Do not allow the variable to point to anything else 不要让变量指向其他任何东西

I simply assumed these 2 goals were needed when defining constant strings. 我只是假设在定义常量字符串时需要这两个目标。

Another interesting thing is that I am allowed to do this: 另一个有趣的事情是我被允许这样做:

int main()
{
    auto MY_CONSTANT = "";
    MY_CONSTANT = "Another String";
}

This tells me that auto deduces the string as char const* and not char const* const . 这告诉我auto将字符串推断为char const*而不是char const* const

So I have two main questions: 所以我有两个主要问题:

  1. What is the most appropriate way to define constant c-style strings (I suppose constant pointers-to-something, is the more general question?). 定义常量c风格字符串的最合适方法是什么(我认为常量指针指向某事,是更普遍的问题?)。 Why do you choose one or the other? 为什么选择其中一个?
  2. Concerning my example with auto , it makes sense why it chooses char const* (because it's the array of data that's constant, not the pointer itself). 关于我使用auto例子,为什么它选择char const*是有道理的(因为它是恒定的数据数组,而不是指针本身)。 Could I make auto deduce to char const* const or can I change the code to make it result in such a type? 我可以auto推导为char const* const还是可以更改代码使其成为这样的类型?

Well if it a truly a constant then constexpr would be the C++11 way to do this: 好吧,如果它真的是一个常数,那么constexpr将是C ++ 11的方法:

constexpr char const* MY_CONSTANT = "Hello World";

The first example: 第一个例子:

static char const* MY_CONSTANT = "Hello World";

just says I have a pointer to a char const that has static storage duration, which if it is outside of a function would make it a global. 只是说我有一个指向具有静态存储持续时间的char const的指针,如果它在函数之外会使它成为全局。

If we required the pointer to also be const then we need the second form your introduced. 如果我们要求指针也是const,那么我们需要你介绍的第二种形式。 It all depends on whether the pointer is indeed supposed to const or not. 这一切都取决于指针是否确实应该是const。 In most cases, the reason your see code without the top-level const is because they just forgot to put it in not because they did not mean the pointer to also be const. 在大多数情况下,你看到没有顶级const的代码的原因是因为他们只是忘了把它放入,因为它们并不意味着指针也是const。

Where static makes a difference for example if whether you want a const member to be per-instance or per-class: 例如, static是否需要const成员是每个实例还是每个类:

class A
{
        char const* const const_per_instance = "Other Const String";
    public:
        constexpr static char const* const const_per_class = "Hello World" ;
};

If we require the const to be per-class then we need to use static otherwise not. 如果我们要求const是每个类,那么我们需要使用静态,否则不需要。 The example changes slightly if you are not allowed to use constexpr : 如果您不允许使用constexpr ,示例会略有变化:

class A
{
        char const* const const_per_instance = "Other Const String";
    public:
        static char const* const const_per_class  ;
};

char const* const A::const_per_class = "Hello World" ;

but the essence is the same just the syntax is different. 但实质是相同的只是语法不同。

For your second question as Gotw #92 says auto drops top level const, one example given is as follows: 对于你的第二个问题,因为Gotw#92表示自动降低顶级const,给出的一个例子如下:

const int   ci  = val;  
auto        g   = ci;

and it says: 它说:

The type of g is int. g的类型是int。

Remember, just because ci is const (read-only) doesn't have any bearing on whether we want g to be const. 请记住,仅仅因为ci是const(只读)与我们是否希望g为const无关。 It's a separate variable. 这是一个单独的变量。 If we wanted g to be const, we would have said const auto as we did in case c above 如果我们想要g为const,我们就像上面的情况c那样说过const auto

the example that is being referred to is as follows: 正在提到的例子如下:

int         val = 0;  
//..
const auto  c   = val;
constexpr auto& MY_CONSTANT = "Hello World";
  • MY_CONSTANT has type const char (&)[12] MY_CONSTANT的类型为const char (&)[12]
  • No decay (the array bound isn't lost) 没有衰减(数组绑定不会丢失)
  • Everything is constant - the array itself and the reference (by definition) 一切都是不变的 - 数组本身和引用(根据定义)
  • Everything is constexpr (can be used at compile time) - the array itself and the reference 一切都是constexpr(可以在编译时使用) - 数组本身和引用
  • MY_CONSTANT has internal linkage due to constexpr and can be used in headers 由于constexpr ,MY_CONSTANT具有内部链接,可以在标题中使用

It's a rare case where it happens that you do overwrite your pointer which points to a const value, therefore most developers omit the second const but semantically it would be indeed correct this way: 这是一种罕见的情况,你碰巧覆盖指向const值的指针,因此大多数开发人员省略了第二个const,但在语义上它确实是这样的:

static char const* const MY_CONSTANT = "Hello World";

or in this form: 或以这种形式:

static const char* const MY_CONSTANT = "Hello World";

constexpr for the declaration is just needed if it is part of another constexpr function like this: 如果它是另一个constexpr函数的一部分,则需要constexpr用于声明:

static constexpr const char* const MY_CONSTANT = "Hello World";
static constexpr const char* Foo()
{
    // ...
    return MY_CONSTANT;
}

Well done for noticing the const on the pointer part! 做得好,注意指针部分的常量! Many people don't realise that bit. 很多人都没有意识到这一点。

To prevent the string literal from being duplicated per translation unit (or make it easier for the string-pooling part of the optimizer), I suggest putting the actual data in a source file somewhere. 为了防止字符串文字被每个翻译单元复制(或使优化器的字符串池部分更容易),我建议将实际数据放在某个源文件中。 This will also save some recompiling if you change the text. 如果更改文本,这也将节省一些重新编译。

header: 标题:

extern const char *const mystring;

source: 资源:

extern const char *const mystring = "hello";

Alternatively 另外

header: 标题:

extern const std::string mystring;

source: 资源:

extern std::string mystring = "hello";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM