Rei*_*ica 5 c++ compiler-errors compiler-warnings language-lawyer
在尝试深入研究这个问题背后的机制之后,我仍然不明白为什么下面代码中的第三行只生成警告,而第二行是错误.
int main()
{
const char* const& a = "bla"; // Valid code
const char*& a2 = "bla"; // Invalid code
char* const& a3 = "bla"; // Should be invalid but settles for a warning
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我知道的是,虽然参考初始化被转换字符串文字的指针参考那么它不应该被丢弃任何cv修饰符对象具有,和作为转换类型const char* const(从字符串文字转换"bla",即,const char[4])这似乎是与第二行相同的情况.唯一的区别是const被删除属于C字符串本身而不是指针.
在没有指定任何额外的一致性标志的情况下在GCC 8.2和Clang 6.0.0上重现.
gcc的输出:
<source>:4:23: error: cannot bind non-const lvalue reference of type 'const char*&' to an rvalue of type 'const char*'
const char*& a2 = "Some other string literal";
^~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:5:23: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
char* const& a3 = "Yet another string literal";
Run Code Online (Sandbox Code Playgroud)
为什么当前的编译器符合第一种情况而不是第二种情况呢?或者,这两种情况之间是否存在根本区别?
mel*_*ene 10
字符串文字是数组.类型"bla"是const char [4].
const char* const& a = "bla";
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为有转换T []为T *; 在这种情况下,你得到一个const char *右值.这个右值可以绑定到一个引用,因为它是一个引用const(它可以保持临时值,等等).
const char*& a2 = "bla";
Run Code Online (Sandbox Code Playgroud)
无效,因为在这里您尝试将临时值绑定到非const引用.
char* const& a3 = "bla";
Run Code Online (Sandbox Code Playgroud)
这是对const的引用,但是类型错误(它是指向char的指针,而不是指向const-char的指针).此转换会删除const限定符,因此它应该无效.一些C++编译器出于向后兼容性的原因允许这样做:在C字符串文字中有一个非const限定类型("bla"即将是a char [4]),因此将其作为一个硬错误会破坏许多现有代码.
即使在C++中,这也是合法的.在C++ 11之前,仍然允许将字符串文字分配给char *(非const char *)变量(但不推荐使用).
"双重标准"是因为永远不允许将非const引用绑定到临时(C甚至没有引用),因此那里没有向后兼容性问题.该标准不区分"错误"和"警告"; 由编译器编写者自行决定编译是否应该对任何给定的违反规则的行为成功.