常见的C++中const常量有哪些用法

来源:站长素材作者:天马头衔:网络博主
导读:本期聚焦于天马创作的《常见的C++中const常量有哪些用法》,敬请观看详情。在C++编程中,const关键字是定义常量的核心工具,很多开发者对它的用法掌握不够全面,容易在开发中遇到相关错误。本文将详细分析C++中const常量的常见用法,包括修饰普通变量、指针、函数参数、函数返回值、类成员等场景,结合实际代码示例讲解每种用法的语法规则和使用注意事项,帮助开发者清晰理解const的作用,在编程中正确运用const提升代码的健壮性和可读性,避免不必要的修改和错误。

在C++编程中,const关键字用于定义不可修改的常量,合理使用const可以让代码更清晰、更安全,避免意外的变量修改。const可以出现在变量、指针、函数参数、函数返回值以及类成员等多个位置,不同位置的使用规则和作用各有侧重。理解这些用法有助于编写更健壮、更易维护的代码。

修饰普通变量

当const直接修饰普通变量时,该变量就成为一个只读常量。它的值必须在声明或定义时完成初始化,并且在初始化之后不能再被修改。如果尝试在后续代码中改变const变量的值,编译器会直接报错,从而在编译阶段就拦截非法操作。

这种用法通常用来替代传统的宏定义。与宏相比,const常量具有明确的类型信息,编译器可以进行类型检查,也便于在调试器中观察变量值。例如,程序中经常出现的一些固定数值,如数组长度、缓冲区大小、版本号等,都适合定义为const变量。

使用const修饰普通变量时还要注意,由于const变量在初始化后不可修改,因此定义时不能只声明而不初始化。在全局作用域中,const变量默认具有内部链接属性,这一点与普通全局变量有所不同,但在实际编程中更常见的是在函数内部或类内部使用。

#include <iostream>
using namespace std;

int main() {
    // const修饰普通变量,定义时必须初始化
    const int MAX_SIZE = 100;
    // 下面的赋值操作会导致编译错误,因为MAX_SIZE不可修改
    // MAX_SIZE = 200;
    cout << "MAX_SIZE的值为:" << MAX_SIZE << endl;
    return 0;
}

修饰指针

const与指针结合时,情况会变得稍微复杂。根据const出现在星号左侧还是右侧,可以分为常量指针和指针常量两种常见形式。二者的核心区别在于:常量指针限制的是指针指向的内容,而指针常量限制的是指针本身的地址。

理解这两种写法需要记住一个简单的判断方法:如果const位于星号的左边,例如const int* p,说明*p是常量,不能通过指针修改指向的值;如果const位于星号的右边,例如int* const p,说明p本身是常量,指针不能重新指向其他地址。

常量指针

常量指针的特点是:指针指向的内容不可修改,但指针本身可以改变指向。也就是说,不能通过该指针去修改它所指向的变量值,但可以让指针重新指向另一个变量。这种用法常用于函数参数中,表示传入的数据只用于读取,不允许被修改。

例如,使用const int* p声明一个常量指针,之后*p = 15这样的赋值语句会直接编译失败,而p = &b则是允许的,因为指针本身的地址没有被限制。

#include <iostream>
using namespace std;

int main() {
    int a = 10;
    int b = 20;
    // 常量指针:const在星号左侧
    const int* p = &a;
    // 下面的操作会编译错误,不能修改指针指向的内容
    // *p = 15;
    // 但指针本身可以重新指向其他地址
    p = &b;
    cout << "p指向的值为:" << *p << endl;
    return 0;
}

指针常量

指针常量的特点与常量指针正好相反:指针本身是一个常量,其指向的地址不能再改变,但可以通过指针修改所指向的内容。声明形式为int* const p,这时p必须在定义时初始化,并且之后不能再指向其他变量。

例如,int* const p = &a;之后,可以执行*p = 15来修改a的值,但不能执行p = &b来改变p的指向。指针常量常用于需要固定访问某一个对象,但又需要修改该对象内容的场景。

#include <iostream>
using namespace std;

int main() {
    int a = 10;
    int b = 20;
    // 指针常量:const在星号右侧
    int* const p = &a;
    // 可以修改指向的内容
    *p = 15;
    // 下面的操作会编译错误,不能修改指针的指向
    // p = &b;
    cout << "a的值为:" << a << endl;
    return 0;
}

修饰函数参数

在函数参数中使用const是一种非常常见的做法。将参数声明为const引用或const指针,既可以避免在函数体内无意中修改传入的数据,又能够避免按值传递带来的拷贝开销。对于较大的对象,如字符串、容器、自定义类等,使用const引用参数尤其合适。

另一个重要优点是,const引用参数可以同时接收const实参和非const实参。如果函数参数没有被声明为const引用,那么当调用者传入一个const对象时,编译器会拒绝调用,因为非const引用不能绑定到const对象上。而使用const引用后,函数的通用性会明显提高。

例如,下面的printName函数接收const string&类型的参数,函数内部只读取该字符串,不会修改它。调用时既可以传入普通字符串变量,也可以传入const字符串变量,编译都能通过。

#include <iostream>
#include <string>
using namespace std;

// 使用const引用参数,避免修改传入的字符串
void printName(const string& name) {
    // 下面的操作会编译错误,不能修改const引用参数
    // name = "test";
    cout << "姓名:" << name << endl;
}

int main() {
    string myName = "张三";
    printName(myName);
    // const对象也可以作为实参传递
    const string constName = "李四";
    printName(constName);
    return 0;
}

修饰函数返回值

const也可以用来修饰函数的返回值,不过这种用法需要根据返回类型来判断是否有效。对于按值返回的情况,返回一个const基本类型或临时对象,实际意义不大。const修饰返回值主要针对返回指针或引用的函数,用来限制调用者通过返回值修改函数内部的数据。

当函数返回一个const指针或const引用时,调用者只能读取该指针或引用所指向的数据,不能通过返回值去修改它。这有助于保护函数内部静态数据或对象成员不被外部随意更改,增强接口的安全性。

下面的示例中,getConstPtr函数返回一个const int*类型的常量指针,该指针指向函数内部的一个静态变量。调用者获得返回值后,只能读取该值,不能通过*p = 60这样的语句修改它,否则会触发编译错误。

#include <iostream>
using namespace std;

// 返回常量指针,防止外部修改返回的地址所指向的内容
const int* getConstPtr() {
    static int num = 50;
    return &num;
}

int main() {
    const int* p = getConstPtr();
    // 下面的操作会编译错误,不能修改常量指针指向的内容
    // *p = 60;
    cout << "获取到的值为:" << *p << endl;
    return 0;
}

修饰类成员

const关键字还可以应用于类的成员变量和成员函数。const成员变量表示该变量在对象创建后不可修改,而const成员函数则承诺在函数执行期间不会修改对象的状态。这两类用法在类设计中非常普遍,有助于明确对象的可变边界。

修饰成员变量

类的const成员变量必须在构造函数的初始化列表中完成初始化,不能在构造函数体内使用赋值语句赋值。这是因为const变量一旦进入构造函数体,其存储空间已经建立,但初始化已经完成,再赋值就会被视为修改操作,从而违反const语义。

例如,Student类中有一个const int id成员,表示学生的学号一旦创建就不能改变。构造函数Student(int studentId) : id(studentId) {}使用初始化列表完成了对id的初始化,这是正确且唯一的做法。

#include <iostream>
using namespace std;

class Student {
private:
    // const成员变量
    const int id;
public:
    // 必须在初始化列表中初始化const成员变量
    Student(int studentId) : id(studentId) {}
    void showId() {
        cout << "学生ID:" << id << endl;
    }
};

int main() {
    Student stu(1001);
    stu.showId();
    return 0;
}

修饰成员函数

在成员函数声明末尾加上const,表示该函数是只读成员函数。这种函数不能修改类的任何非mutable成员变量,也不能调用其他非const成员函数。编译器会对这一约束进行严格检查,一旦发现违规操作就会报错。

有时类中会有一些用于统计或缓存的成员变量,它们并不影响对象的逻辑状态,但又需要在const成员函数中修改。这时可以使用mutable关键字修饰这些成员变量,允许它们在const成员函数中被修改。例如下面的Book类中,readCount被声明为mutable,因此getTitle这个const成员函数可以递增readCount,而普通成员title则不能被修改。

const成员函数还有一个重要作用:const对象只能调用const成员函数。如果一个对象被声明为const,那么尝试调用非const成员函数会编译失败。因此,为那些不改变对象状态的成员函数加上const修饰,可以提高对象的可用范围。

#include <iostream>
#include <string>
using namespace std;

class Book {
private:
    string title;
    mutable int readCount; // mutable成员可以在const函数中被修改
public:
    Book(string t) : title(t), readCount(0) {}
    // const成员函数
    string getTitle() const {
        // 下面的操作会编译错误,不能修改非mutable成员变量
        // title = "new title";
        // 可以修改mutable成员
        readCount++;
        return title;
    }
    void showReadCount() const {
        cout << "阅读次数:" << readCount << endl;
    }
};

int main() {
    const Book book("C++入门教程");
    cout << "书名:" << book.getTitle() << endl;
    book.showReadCount();
    return 0;
}

总结与使用建议

const关键字在C++中贯穿变量、指针、函数和类的各个方面,是保证代码安全性和表达意图的重要工具。使用const修饰不会修改的数据,能够让编译器在编译阶段发现潜在的非法修改,减少运行时错误。

在实际编程中,建议优先使用const修饰函数中只读的引用参数和指针参数,同时为不会改变对象状态的成员函数添加const限定。对于明确不变的常量,使用const替代宏定义;对于指针场景,要特别注意区分常量指针和指针常量的语义差异。合理运用const,可以让代码接口更加清晰,也更容易理解和维护。

const常量C++修改时间:2026-07-19 20:33:27

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。