const成员变量只能在构造函数初始化列表中初始化,构造完成后不可修改,否则报assignment of read-only member错误。

为什么 const 成员变量被赋值会报这个错
编译器报 assignment of read-only member,本质是因为你试图在对象构造完成之后,给一个声明为 const 的成员变量重新赋值。C++ 规定:一旦 const 成员被初始化(只能在构造函数初始化列表中),它在整个对象生命周期内不可修改。
常见误操作包括:
- 在构造函数体内部用
=给const成员赋值(如this->x = 10;) - 在普通成员函数里直接写
x = 20;(哪怕函数加了const修饰也不行) - 调用非
const函数时,传入的是const对象引用,而函数内部尝试改其const成员
怎么快速定位是哪个成员、哪行代码触发的
错误信息末尾通常带字段名,比如:assignment of read-only member 'A::value'。顺着这个线索查:
- 搜索类
A定义,确认value是否声明为const int value;或类似形式 - 全局搜索
A::value =、.value =、->value =,重点看是否出现在构造函数体、赋值运算符、set_*类函数中 - 如果用了聚合初始化或
std::make_unique等间接方式创建对象,检查初始化逻辑是否遗漏了该const成员的初始化列表项
注意:初始化列表里漏写 value(0) 不会立刻报错,但后续任何赋值都会触发此错误——所以“没初始化”和“初始化后又赋值”是两种不同问题,别混淆。
修复方法:必须用初始化列表,且只在这里赋值
const 成员唯一合法的赋值时机,是构造函数的初始化列表。不能在函数体内做。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
class Config {
public:
const int timeout;
const std::string name;
// ✅ 正确:全部在初始化列表中完成
Config(int t, std::string n) : timeout(t), name(std::move(n)) {}
// ❌ 错误:以下写法编译不过
// Config(int t) { timeout = t; }
};
如果你需要运行时决定值,又想保持语义上的“只读”,考虑:
- 把字段改成
mutable int timeout;(仅当配合const成员函数内部逻辑缓存等场景) - 用
std::optional<int></int>替代const int,延迟初始化(但不再有编译期只读保证) - 彻底去掉
const,靠文档或命名(如m_timeout_)约定只读——适合配置类中部分字段实际允许重载的场景
容易忽略的坑:基类 const 成员 + 派生类构造
如果基类有 const 成员,派生类构造函数必须显式调用基类构造函数并传参,否则基类 const 成员无法初始化。
class Base {
protected:
const int id;
Base(int i) : id(i) {}
};
class Derived : public Base {
public:
// ❌ 编译失败:Base::id 未被初始化(Derived 构造函数没调用 Base(int))
Derived() {}
// ✅ 正确:必须显式委托
Derived(int i) : Base(i) {}
};
这种错误不会直接提示 “read-only member”,而是先报基类无默认构造函数,但根源仍是 const 成员缺失初始化。排查时要往继承链上多看一层。
最麻烦的情况是模板类嵌套、constexpr 构造、或使用 std::variant 存储含 const 成员的对象——此时初始化逻辑分散,建议优先避免在可变对象中放 const 成员,除非明确需要编译期只读语义。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










