You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在const引用对象上修改引用值的代码可在MSVC、Clang编译?

为啥const引用对象上修改内部引用值能编译通过?

这个问题其实戳中了C++里const限定符和引用成员结合时的一个容易踩的坑,我来给你拆解清楚~

首先先还原一下你大概率遇到的代码场景(毕竟没贴代码,但根据描述应该是类似这样):

#include <iostream>

class Test {
public:
    int& val_ref;
    Test(int& x) : val_ref(x) {}
};

int main() {
    int num = 5;
    const Test const_obj(num);
    const_obj.val_ref = 10; // 你疑惑的就是这行为啥能编译过?
    std::cout << num << std::endl; // 输出10
    return 0;
}

核心原因:const修饰的是「对象本身」,而非「成员引用指向的外部对象」

当你声明const Test const_obj时,const限定的是const_obj这个Test类型的对象,而不是它的成员val_ref所引用的num。

那const对Test对象的成员到底有啥影响?

  • 对于普通成员变量(比如int val;),const对象里的这个成员会被自动视为const int,你绝对不能修改它的值;
  • 但对于引用成员,情况完全不同:引用本身不是一个独立的对象,它只是某个变量的「别名」。C++里根本不存在int& const这种写法——因为引用一旦初始化就不能被重新绑定,给引用加const完全是多此一举,编译器也不允许这种语法。

所以当你有一个const的Test对象时,它的引用成员val_ref的类型仍然是int&,而不是const int&。const限定符只能保证你不能修改const_obj本身的成员(但引用成员本身没法被修改绑定,所以这条限制对引用来说等于没生效),但完全不限制你通过这个引用去修改它指向的外部变量。

对比指针成员更容易理解

如果你把成员换成指针,逻辑会更直观:

class Test {
public:
    int* val_ptr;
    Test(int* x) : val_ptr(x) {}
};

int main() {
    int num = 5;
    const Test const_obj(&num);
    *const_obj.val_ptr = 10; // 这行也能编译过!
    // const_obj.val_ptr = &another_num; // 这行不行,因为const对象的指针成员是int* const,不能改指针本身的指向
    return 0;
}

这里const对象的指针成员是int* const(指针本身是const,不能改指向),但指针指向的对象仍然是可修改的——和引用成员的逻辑完全一致:const只限制对象本身的成员,不限制成员指向/引用的外部对象。

怎么让const对象的引用成员不能修改外部变量?

如果你想达到「const对象的引用成员不能修改指向的变量」的效果,需要把类的引用成员直接声明为const int&:

class Test {
public:
    const int& val_ref;
    Test(const int& x) : val_ref(x) {}
};

int main() {
    int num = 5;
    const Test const_obj(num);
    // const_obj.val_ref = 10; // 这行就会编译报错了!
    return 0;
}

这样不管对象是不是const,引用成员都是const引用,无法通过它修改外部变量。

内容的提问来源于stack exchange,提问作者UfoXp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:26:47