这是我的问题,问题在注释中
const int a = 5;
const_cast<int&>(a)=7; //throw over const attribute in a,and assign to 7
std::cout<<a<<std::endl; //why still out put 5!!!!!!!!!!
有谁能告诉我为什么?还有一些书籍解释了这些问题并进行了推荐。谢谢!
这是我的问题,问题在注释中
const int a = 5;
const_cast<int&>(a)=7; //throw over const attribute in a,and assign to 7
std::cout<<a<<std::endl; //why still out put 5!!!!!!!!!!
有谁能告诉我为什么?还有一些书籍解释了这些问题并进行了推荐。谢谢!
就你目前的写法而言,这是未定义行为。如果你想以明确定义的方式查看 const_cast<>
的效果:
int a = 5; // note: not const. regular object.
const int& cref = a; // const-reference to same object.
cref = 7; // illegal. cref is a const reference.
const_cast<int&>(cref) = 7; // legal. the original object a is not const.
由于原始变量a的非常量性质,这才是定义行为的唯一原因。你不能取出一个明确被限制为常量的对象并简单地强制转换掉其常量属性,这就是你发布的代码所做的事情(至少在我多次解释的时候是这样)。const int a;
编译器有时会将该值存储在ROM中,程序的整个生命周期内都无法修改。因此,在创建时声明为const的值上强制取消const是未定义的行为。在稍后的某个时间点将非const值称为const,允许编译器强制执行对于程序的一部分值不会改变的限制。这些值可以以一种定义良好的方式取消其const属性,但通常这种转换是设计不良的标志。 - YoungJohnC++标准草案第7.1.6.1
节The cv-qualifiers第4段指出:
[...]在其生命周期(3.8)内尝试修改const对象会导致未定义行为
因此,任何行为都是可能的,但您不应该这样做,绝不能依赖于这种行为。当然,正如const_cast是否安全?中接受的答案所说,const_cast确实有有效的用途:
我们可以从这个 实例 看到你所看到的结果可能发生的一种情况,只有在转换最初非常量变量时,const_cast才是安全的[...]
gcc 4.8.1
没有进行任何优化,只使用值 5
而不是读取当前值:movl $7, (%rax)
movl $5, %esi
movl $_ZSt4cout, %edi
movl $7, -4(%rbp)
movl -4(%rbp), %eax
movl %eax, %esi
movl $_ZSt4cout, %edi
cout
语句相同作用域内定义的 a
常量时,很可能根本不会去查看内存。volatile const int a = 5;
std::cout << 5 << std::endl;
。 - chrisconst
是非常量。编译器有许多手段惩罚不诚实的程序员;-)(编译器反击的官方名称是“未定义行为”)。 - Sergey Kalinichenko