【问题标题】:Behavior of const reference after casting to non-const转换为非常量后 const 引用的行为
【发布时间】:2017-03-12 14:27:24
【问题描述】:

我对下面的代码有点困惑。 b 如何仍然引用 a 但具有不同的值?

#include <iostream>
using namespace std;
int main()
{
    const int a = 5;
    const int &b = a;
    ++(int&)b;
    cout << a << endl;//returns 5
    cout << b << endl;//returns 6
    cout << "mem a:" << &a << endl; //returns 0x61ff18
    cout << "mem b:" << &b << endl; //returns 0x61ff18
    return 0;
}

【问题讨论】:

    标签: c++ c++11 reference constants


    【解决方案1】:

    此行为未定义。

    您可以合法地从非常量对象的常量引用中转换常量;但是,从引用真实 const 的引用中强制转换 const-ness 会导致未定义的行为。

    在这种情况下,编译器似乎创建了一个内存位置来存储5,以便为您提供一个可以引用b的位置,而变量a本身被优化为一个常量.你的代码非法修改了b引用的位置,产生6,而行

    cout << a << endl;
    

    优化成

    cout << '5' << endl;
    

    所以它仍然会产生一个5

    【讨论】:

    • 你说得对,编译器似乎用 5 替换了表达式 a,所以它毕竟不是真正的“未定义”。谢谢
    • @danwin 嗯,是的。编译器选择做一些容易解释的事情是无关紧要的。它仍然是未定义的行为。
    • @danwin:C++ ISO 标准未定义该行为。这并不意味着无法推断编译器产生的行为;它只是意味着你不能可靠地使用 C++ 规则来推理它。
    • 请注意,“未定义的行为”并不意味着“会发生不好的事情”。它only表示C++语言定义没有告诉你代码做了什么。
    【解决方案2】:

    在这种情况下,您的 C 风格转换等效于 const_cast。而使用const_cast 抛弃原本不变的事物的常量性,然后尝试修改它是未定义的行为。您观察到的所有行为都被认为是随机的,没有任何意义。


    如果对象最初是非常量的,您可以安全地使用const_cast

    #include <iostream>
    
    int main()
    {
        int a = 5; // <--- non-constant
        const int &b = a;
        ++const_cast<int&>(b);
        std::cout << a << '\n'; // 6
        std::cout << b << '\n'; // 6
        std::cout << "mem a:" << &a << '\n';
        std::cout << "mem b:" << &b << '\n';
    }
    

    【讨论】:

    • “而使用 const_cast 来抛弃原本不变的事物的 constness 是未定义的行为” 不,不是。
    • @LightnessRacesinOrbit:我起初认为这很明显,但我想你是对的,它很容易被误解为最初的措辞。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-27
    • 2020-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    • 2020-07-20
    相关资源
    最近更新 更多