C++ const_cast(char*const)不是左值?

C++ const_cast(char*const)不是左值?,c++,language-lawyer,c++17,lvalue,const-cast,C++,Language Lawyer,C++17,Lvalue,Const Cast,在编译下面的代码时,我在第3行得到一个错误,关于const_cast不是左值的结果。这仅仅是因为我使用了GCC7.x,尽管它应该完全符合C++17,但这是一个问题吗?或者根据标准,这确实是无效代码吗 下面的代码是触发错误的最小示例。尝试了gcc 7.1、7.4,也得到了相同的错误 char* const a = "xyz"; char* b; const_cast<char*>(a) = b; // not lvalue error gcc给出的精确错误是:error:赋值的左操

在编译下面的代码时,我在第3行得到一个错误,关于const_cast不是左值的结果。这仅仅是因为我使用了GCC7.x,尽管它应该完全符合C++17,但这是一个问题吗?或者根据标准,这确实是无效代码吗

下面的代码是触发错误的最小示例。尝试了gcc 7.1、7.4,也得到了相同的错误

char* const a = "xyz";
char* b;
const_cast<char*>(a) = b;  // not lvalue error
gcc给出的精确错误是:error:赋值的左操作数需要左值

注:忘了添加:该示例与我将要编写的实际代码无关。这是我举的一个例子,我想这是为了测试人们对标准的理解程度。因此,我只对我在问题中提出的问题感兴趣,即,这是否是有效代码,以及为什么。谢谢

类型char*const a定义了一个指针变量a,该变量不能更改,但指向可以更改的字符。这不是使指针为常量的常用方法

错误是告诉您不能更新a的值-它不是左值,我不相信const_cast在这种情况下可以绕过它


你可能指的是const char*a,它允许改变指针本身,但不允许改变指向的对象吗?

左值是一种语法结构,意思是一种可以出现在赋值左边的表达式。您可以分配给变量、数组组件或字段,但将分配写入其他类型的表达式(如x+y=7)是一个语法错误;或fx=5;。诸如const_casta之类的函数调用不是一种可以赋值的表达式

写a=const_castb;,在语法上是有效的;,函数调用出现在赋值的右侧

因此,我只对我在问题中提出的问题感兴趣,即,这是否是有效代码

不是。const_cast的结果只有在转换为引用类型时才是glvalue左值或xvalue

[expr.const.cast]强调矿山

表达式const­castv的结果为类型 如果T是对对象类型的左值引用,则结果是 左值;如果T是对对象类型的右值引用,则结果是 xvalue;否则,结果为prvalue,并且 左值到右值,数组到指针,函数到指针标准 对表达式v执行转换。可以进行的转换 下面列出了使用常量显式执行的。没有别的 应使用常量显式执行转换

您不强制转换为引用类型,因此结果是一个prvalue;不是你可以指定的东西。也不要将其转换为引用类型;试图修改声明为常量的对象会产生未定义的行为。您的程序将是另一种无效程序。

首先,char*const a=xyz;这是违法的。字符串文字的类型为const char[N],并将其分配给char*const将删除在隐式转换中非法的字符常量

现在,让我们假装一切正常,让我们看看

const_cast<char*>(a) = b
这有两个问题。第一个是const_casta导致右值。对于非类类型,不能将其分配给右值。您需要const_casta来分配一个左值,这就带来了下一个问题。不能指定给常量对象。使用const_cast剥离const并不能解决这个问题。这仍然是不允许的

在常量对象[basic.type.qualifier]的生存期[basic.life]内修改[expr.ass]、[expr.post.incr]、[expr.pre.incr]的任何尝试都会导致未定义的行为


即使使用正确的强制转换,底层对象仍然是常量,因此您违反了上述子句,并且具有未定义的行为。

a是左值。它的const_casta不是。clang说::5:3:错误:对cast的赋值是非法的,不支持左值强制转换。我在这行char*const a=xyz上得到一个错误;实时检查您的错误/警告级别:很少有需要const_cast的情况。在您使用该语言达到专家级之前,您应该避免使用它。当您将一个标记为const时,编译器可以将其放在只读内存中。即使没有,它也可以假设您从未修改过,因为它是常量。即使您解决了特定的编译器错误,这也不会按照您想要的方式工作。请非常非常小心地处理const_cast。如果您要丢弃的const对象最初没有声明为non-const,那么修改它是未定义的行为,并且您的程序没有意义,编译器可能会执行任何操作。const_cast是一个非常尖锐/危险的工具,很难正确使用,通常最好完全避免。@user12304836我只对我在问题中提出的问题感兴趣,即,这是否是有效代码-在您的示例中,a声明为const,因此修改它是非法的
阿尔-即使是在一个康斯图演员之后。丢弃常量后修改对象是合法的唯一情况是,该对象最初声明为非常量,但您收到了指向它的常量引用或指针。在这种情况下,丢弃常量并修改object.fx=5是有效的,尽管样式非常糟糕;如果fx返回一个引用,例如int&fint;,则完全可以-这只是事实的一半。有很多实例可以为函数的返回赋值。事实上,康斯特·卡斯塔(const_casta)将消除错误代码,但代码仍然被破坏。哇,我很惊讶人们能如此迅速地给出答案并为我澄清问题。非常感谢大家,特别是纳撒诺利弗、讲故事的人和杰斯珀·尤尔的详细解释。[我是否应该关闭问题或将答案标记为最佳答案???@user12304836如果您希望选择您最喜欢的答案并单击复选标记。这会给你和回答者带来额外的声誉。这个问题不需要结束。另外,不客气。谢谢!这是一个艰难的决定,最终我选择了讲故事的人。