【发布时间】:2020-08-28 15:47:12
【问题描述】:
此声明:
char constexpr *const s = "hello";
失败并出现此错误:
g++ -g -Wall -Werror -std=c++17 test.cc -o test
test.cc:8:31: error: ISO C++11 does not allow conversion from string literal to 'char *const' [-Werror,-Wwritable-strings]
char constexpr *const s = "hello";
但是如果我将 const 添加到 constexpr,编译器会很高兴:
char const constexpr *const s = "hello";
编译:
g++ -g -Wall -Werror -std=c++17 test.cc -o test
./test
hello
这对我来说似乎不直观。为什么const需要修饰constexpr? constexpr 不意味着 const 吗?如果它是编译器常量,那么它在其他意义上怎么不是常量?是否有可能某些东西是 constexpr 但以其他方式改变而不是恒定的?
这是一个最小的神螺栓:
更新:
StoryTeller 的回答是理解这一点的关键。我已经接受了他的回答,但我会在这里扩展它,以防其他人试图理解这一点。与 const 交互时,我习惯于将 const 视为应用于其左侧的项目。因此:
char a[] = "hello";
char * const s = a;
s[0] = 'H'; // OK
s = "there"; // Compiler error.
这里,char * const s 表示指针 s 是 const 而它取消引用的字符是可修改的。另一方面:
char const * s = "hello";
a[0] = 'H'; // Compiler error
s = "there"; // OK
在这种情况下,char const * s 表示 s 指向的字符是 const,而不是指针。
好的,大多数使用过 const 和指针的人都明白这一切。我被抛弃的地方是我认为 constexpr 也会以这种方式工作。也就是说,鉴于此:
char constexpr * const s = "hello";
我认为这意味着指针是 const(它是)并且字符本身是 const 和 constexpr。但是语法不是那样工作的。相反,在这种情况下的 constexpr:
- 不适用于角色,而是...
- 适用于
s本身,它是一个指针,并且... - 因此与指针后面的 const 是多余的。
因此,在这种情况下,没有在字符上声明 const。事实上,如果我完全删除 constexpr,我会得到完全相同的错误:
char * const s = "hello"; // Produces same error as char constexpr * const s = "hello";
但是,这有效:
constexpr char const * s = "hello";
上面有我们想要的,意思是:
- 字符是常量,通过
const - 而指针
s是const 和一个编译时间常数通过constexpr
【问题讨论】:
-
很好的解释!谢谢。