C++初始化 和 赋值

一、先看反例:试图在构造函数体中 "初始化" const 成员(编译报错)

先运行这段代码,你会发现编译器直接报错,根本无法通过:

cpp 复制代码
#include <iostream>
using namespace std;

class Test {
private:
    const int num; // const成员变量

public:
    // 错误写法:试图在构造函数体中给const成员赋值
    Test(int val) {
        num = val; // 编译报错!const变量不能被赋值
    }

    void show() {
        cout << "num = " << num << endl;
    }
};

int main() {
    Test t(10);
    t.show();
    return 0;
}

编译错误信息(以 GCC 为例)

cpp 复制代码
error: assignment of read-only member 'Test::num'
     num = val;
         ^
错误原因:
  • const成员变量的特性是:只能在 "初始化" 阶段赋值,一旦初始化完成,就不能再被修改(赋值)
  • 构造函数的执行分为两步:
    1. 初始化阶段 :在{}之前,通过初始化列表完成成员变量的初始化(这是 const 成员唯一能被赋值的时机);
    2. 赋值阶段 :进入{}后的构造函数体,此时所有成员变量(包括 const)已经完成初始化,再给 const 成员赋值就会触发 "修改只读变量" 的错误。

二、为什么你会误以为 "可以在构造函数体初始化"?

可能是你看到过类似这样的代码(但其实是初始化列表的简写 / 编译器优化误解):

cpp 复制代码
// 正确写法:用初始化列表,只是你可能忽略了初始化列表的存在
class Test {
private:
    const int num;

public:
    // 正确:初始化列表初始化const成员,构造函数体无操作
    Test(int val) : num(val) { 
        // 这里是构造函数体,num已经初始化完成,不能再赋值
    }
};

三、再验证:const 成员必须用初始化列表的核心逻辑

表格

操作场景 是否可行 本质原因
初始化列表 num(val) ✅ 可行 初始化阶段,给 const 变量赋初值
构造函数体 num = val ❌ 不可行 赋值阶段,修改只读变量
类内直接初始化 const int num = 10; ✅ 可行 C++11 及以上支持,本质也是初始化

补充:C++11 后支持 "类内直接初始化" const 成员(如const int num = 10;),但这只是初始化列表的语法糖 ------ 编译器会自动把这个初始值放到默认构造函数的初始化列表中。如果有自定义构造函数,仍需通过初始化列表指定 const 成员的初始值。


四、完整可运行示例(正确用法)

cpp 复制代码
#include <iostream>
using namespace std;

class Test {
private:
    const int num; // const成员变量

public:
    // 正确:初始化列表初始化const成员
    Test(int val) : num(val) {
        cout << "const成员num已初始化:" << num << endl;
        // num = 20; // 打开注释会编译报错:修改只读变量
    }

    void show() {
        cout << "num = " << num << endl;
    }
};

int main() {
    Test t1(10); // 初始化num=10
    t1.show();   // 输出:num = 10

    Test t2(20); // 初始化num=20
    t2.show();   // 输出:num = 20
    return 0;
}

输出结果

cpp 复制代码
const成员num已初始化:10
num = 10
const成员num已初始化:20
num = 20

总结

  1. 核心区别const成员的 "初始化"(初始化列表)和 "赋值"(构造函数体)是两个不同阶段,const 变量仅允许在初始化阶段赋值;
  2. 语法规则 :构造函数体中无法给 const 成员赋值,只能通过初始化列表(或 C++11 类内直接初始化)完成 const 成员的初始化;
  3. 本质原因:const 变量的只读特性决定了它必须在创建时(初始化阶段)确定值,后续无法修改。
相关推荐
点心的游戏开发世界14 分钟前
GDScript 入门笔记:目录
开发语言·笔记·游戏引擎·godot
洋不写bug21 分钟前
二叉树(二) 常见基础操作解析|结点数、树高、查找结点、判断完全二叉树
java·开发语言·数据结构·完全二叉树·二叉树结点数·树高·查找结点
果果燕24 分钟前
实习笔记(六)主机按钮状态上报完整流程
开发语言·c++·php
平头哥技术团队1 小时前
Day 16 | 用 ul、ol、li 一个标签,把散资料收成有序的技能清单页
开发语言·前端·html·html5
是个西兰花1 小时前
网络基础1
linux·网络·c++·智能路由器
统计学小王子1 小时前
数学建模国赛倒计时 2 天 ——《统计模型精讲(广义线性模型 R 语言实例 + 分析)》
开发语言·数学建模·r语言
此冬歌咏1 小时前
自动化服务器运维监控系统(python+shell)
linux·运维·服务器·开发语言·python·自动化
老赵的博客1 小时前
c++QT之动态库加载常见报错
c++·qt
wabs6662 小时前
关于二叉树【429.N叉树的层序遍历的思考】
数据结构·c++·算法·leetcode·二叉树
Cx330❀2 小时前
【Linux网络】深入TCP协议:从滑动窗口到拥塞控制与性能优化全景解析
linux·开发语言·网络·tcp/ip·ai·性能优化·ai编程