【问题标题】:behavior of const_cast in C++ [duplicate]C ++中const_cast的行为[重复]
【发布时间】:2014-01-03 08:49:49
【问题描述】:

这是我的问题,问题出在 cmets

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!!!!!!!!!!

谁能告诉我为什么,推荐一些书籍说明这些问题? 谢谢!

【问题讨论】:

  • 这是未定义的行为。它可以为所欲为。查看编译器的输出代码。可能只是std::cout &lt;&lt; 5 &lt;&lt; std::endl;
  • 你在向你的编译器撒谎,说 const 是非常量的。编译器有讨厌的方式来报复你,因为你不诚实;-)(编译器回击你的官方名称是“未定义的行为”)。
  • 但是在中,作者使用了类似的东西:se是一些实现中的集合,其中集合的键是const,Emp::iterator i = se.find(... );... const_cast(*i).setValue(someValue);为什么可以工作?
  • @Ryan_Liu 您能否将有效 STL 示例的完整示例粘贴到上述问题的底部?如果没有完整的上下文,很难告诉你为什么它(大概)是有效的......
  • @Ryan_Liu 对于有效的 STL 问题,如果您在知道实际上不是 const 的东西上 const_casting 掉 const(在这种情况下,容器节点的内容),这不是未定义的行为.

标签: c++ undefined-behavior const-cast


【解决方案1】:

您这样做的方式是未定义的行为。如果您想以明确的方式查看const_cast&lt;&gt; 的效果:

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 object 并简单地抛弃 const-ness,这就是您发布的代码所做的。 (至少已经多次向我解释过)。

【讨论】:

  • 所以说,当编译器遇到一个 const 值时,例如: const int a;编译器有时可以将该值存储在 ROM 中,该值在程序的生命周期内永远不会被修改。因此,在创建时声明为 const 的值上丢弃 const 是未定义的行为。在稍后的某个时间点调用非常量值 const 允许编译器强制执行该值对于程序的一部分不会改变。这些值可以以定义的方式丢弃它们的常量,但当需要这种转换时,这通常是设计不佳的标志。
【解决方案2】:

draft C++ standard 部分 7.1.6.1 cv-qualifiers 段落 4 说:

[...]在 const 对象的生命周期 (3.8) 内修改任何尝试都会导致 undefined behavior

所以任何行为都是可能的,但你不应该这样做,你绝对不能依赖这种行为。当然 const_cast 确实有有效的用途,因为Is const_cast safe? 中接受的答案说:

const_cast 仅在您转换一个原本是非 const 的变量时才是安全的。[...]

我们可以从live example 看到您看到的结果的一种方式,即 gcc 4.8.1 没有任何优化只是使用值 5 而不是读取当前值:

movl    $7, (%rax)
movl    $5, %esi
movl    $_ZSt4cout, %edi

non const 的情况下,我们将看到如下内容:

movl    $7, -4(%rbp)
movl    -4(%rbp), %eax
movl    %eax, %esi
movl    $_ZSt4cout, %edi

【讨论】:

    【解决方案3】:

    编译器在欺骗你,因为这(编辑:你在上面使用它的方式。)是明确未定义的行为。当它看到在与cout 语句相同的范围内定义的a 常量时,很可能甚至都不会费心查看内存。

    你可以做一个更人为的例子来欺骗你的编译器,但是下面的修改至少在 gcc 中给了我你想要的结果:

    volatile const int a = 5;
    

    为了澄清,并非所有 const_cast 使用都是未定义的行为,请参阅 WhozCraig 的示例。

    【讨论】:

    • 但是在中,作者使用了类似的东西:se是一些实现中的集合,其中集合的键是const,Emp::iterator i = se.find(... );... const_cast(*i).setValue();为什么可以工作?
    • 编译器在欺骗程序员?我会说这是相反的方式。 ;)
    • @Ryan_Liu 编写 const 方法(即不会修改非可变成员的方法)有一些众所周知的模式,可以通过明智的 const_cast 使用避免与非常量版本的代码重复。是这样吗?
    • @Jim 不,伙计,程序员永远是对的,对吧? :)
    • 使用 volatile 可能会改变明显的行为,但修改 const 变量仍然是未定义的行为。
    猜你喜欢
    • 2014-06-06
    • 2013-03-16
    • 2016-10-09
    • 2021-05-16
    • 2018-11-15
    • 1970-01-01
    • 2011-11-13
    • 2021-11-15
    相关资源
    最近更新 更多