C++ const关键字

C++ const关键字

记得有次面试carmera turning岗,面试官让我谈谈const关键字的作用我提到被const修饰变量会存入.rodata的只读数据段不可更改,面试官好像不是很满意,现在想想carmera turning岗位好像主要用C++,面试官当时是想让我说说C++中const关键字的作用。C++中const关键字的作用比起C语言就多了不少。

1. 用于声明常量

常量一旦被初始化,就不能被修改。在C++中被const修饰的变量仅在当前文件中可见

const int MAX_SIZE = 100; // 声明一个常量
MAX_SIZE = 200; // 错误:常量不能被修改

2. 指向常量的指针

指向常量的指针表示指针所指向的值是常量,不能通过指针修改该值。

const int* ptr; // 指向常量的指针
int value = 5;
ptr = &value;
// *ptr = 10; // 错误:不能通过指针修改常量值

3. 常量指针

常量指针表示指针本身是常量,不能改变指针指向的地址。

int value = 5;
int* const ptr = &value; // 常量指针
*ptr = 10; // 合法:可以通过常量指针修改指针指向的值
// ptr = nullptr; // 错误:不能改变常量指针的指向

4. 常量成员函数

成员函数的末尾增加一个const会变为常量成为函数,这个成员函数不会修改该对象里面的任何成员变量的值等。

void noone() const
{
    Hour += 10;   //错误,常量成员函数不可以修改成员变量值
}

注意:

普通函数(非成员函数)末尾是不能加const的。

成员函数的声明和实现代码分开的情形下,不但要在成员函数的声明中增加const,也要在成员函数的实现中增加const。

5.常量对象

const MyClass obj;
obj.display();

被const修饰的对象,只能调用常量成员函数,且不能修改成员变量。

mutable

被mutable修饰的成员变量永远处于可变状态,即使是在常量成员函数中。引入mutable关键字的意义在于,满足在某些情况下需要常量对象,调用常量成员函数修改一些特定值的情况。

class Time {
private:
    mutable int myHour;    // 允许在const成员函数中修改
    int myMinute;
    int mySecond;

public:
    void noon() const {
        myHour = 12;  
    }
};

6.修饰函数参数

输入参数采用“指针传递”加 const 修饰可以防止意外地改动该指针,起到保护作用。

void StringCopy(char *strDestination, const char *strSource);

常量左值引用

void Func(const A &a)

相较于void Func(A a)的写法上面的写法传入引用省去了临时对象的构造、复制、析构过程,加入const变为常左值引用防止参数被意外修改,而且既可以接受左值引用,又可以接受右值引用,增加程序的通用性。

7.修饰函数返回值

const 修饰内置类型的返回值,修饰与不修饰返回值作用一样。

#include<iostream>
 
using namespace std;
 
const int Cmf()
{
    return 1;
}
 
int Cpf()
{
    return 0;
}
 
int main(void)
{
    int _m = Cmf();
    int _n = Cpf();
 
    cout<<_m<<" "<<_n;
    system("pause");
    return 0;
}

const 修饰自定义类型的作为返回值,此时返回的值不能作为左值使用,既不能被赋值,也不能被修改。

#include <iostream>

class MyClass {
public:
    MyClass(int value) : value_(value) {}
    int getValue() const { return value_; }
    void setValue(int value) { value_ = value; }

private:
    int value_;
};

// 返回一个const MyClass对象的引用
const MyClass getConstObject() {
    static MyClass obj(10);
    return obj;
}

int main() {
    //不可被赋值
    MyClass newObj(20);
    getConstObject() = newObj;
    //不可被修改
    getConstObject().setValue(20); 
    //不可作为左值
    MyClass& objRef = getConstObject();
    return 0;
}

const 修饰指针作为返回值,函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加 const 修饰的同类型指针。

const int* getConstPointer() {
    static int* a;
    return a;
}

int main() {
    const int* p = getConstPointer();//不能去掉const
    return 0;
}

constexpr

constexpr 变量在编译时必须能够求值。这意味着编译器在编译时就可以确定该变量的值。

constexpr int max_size = 100; // 编译时常量

constexpr 函数

constexpr 函数是一种在编译时可以计算其返回值的函数。为了成为 constexpr 函数,该函数必须满足一些条件,例如函数体必须包含一个返回语句,并且所有参与计算的参数和操作都必须是编译时可知的。

constexpr int factorial(int n) {
    return (n <= 1) ? 1 : (n * factorial(n - 1));
}

在上面的例子中,factorial 函数在编译时即可计算其结果:
constexpr int result = factorial(5); // result 在编译时计算出 120

constexpr 构造函数

在 C++11 及其后的标准中,构造函数也可以被标记为 constexpr,这允许在编译时创建常量表达式对象。

class Point {
public:
    constexpr Point(double x = 0, double y = 0) : x_(x), y_(y) {}
    constexpr double getX() const { return x_; }
    constexpr double getY() const { return y_; }
private:
    double x_;
    double y_;
};

constexpr Point p(3.0, 4.0);
constexpr double x = p.getX(); // x 在编译时计算出 3.0
constexpr double y = p.getY(); // y 在编译时计算出 4.0

constexpr 和 const 的区别

const 仅表示对象不可修改,但不要求编译时求值。
constexpr 要求表达式在编译时求值,因此可以用于定义编译时常量。
constexpr 的限制
为了使函数成为 constexpr,需要满足以下条件:

函数必须有一个返回值。
函数体必须是一个编译时常量表达式。
参数和返回值都必须是字面值类型(literal types)。

posted @   紫冰凌  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示