C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++  const用法

C++ 的 const 相关知识点总结

作者:basketball616

这篇文章详细介绍了C++中的const关键字,包括基础概念、指针和const的关系、顶层const与底层const的区别、const在函数和成员函数中的应用、mutable的关键字作用,感兴趣的朋友跟随小编一起看看吧

const 大概是 C++ 初学者最早接触的关键字之一,但它绝不仅仅表示“一个不可修改的常量”。随着学习的深入,你会发现它在类型安全、编译器优化、接口设计乃至多线程编程中都扮演着重要角色。

1. 基础篇:定义一个常量

最简单的用法,让变量值不可修改。

const int MAX_SIZE = 100;
// MAX_SIZE = 200; // 错误!不能修改
int const MAX_SIZE_2 = 100; // 与上一行完全等价,const 在类型前后均可

要点

const 与宏常量的区别

在 C++ 中,更推荐使用 constconstexpr 代替 #define 定义常量,因为它有类型检查,且遵循作用域规则。

2. 指针与 const:厘清谁是不可变的

这是最绕也是面试最爱考的地方。记住核心:看 const 在 * 的哪一边

2.1 指向常量的指针

int value = 10;
const int* ptr = &value; // 等同于 int const* ptr

2.2 常量指针

int value = 10;
int* const ptr = &value;

2.3 指向常量的常量指针

const int value = 10;
const int* const ptr = &value;

记忆技巧:以 * 为界,const 在左修饰指向的对象,在右修饰指针本身。所以 const int * 修饰的是 intint * const 修饰的是指针。

3. 顶层 const 与底层 const

这个概念在泛型编程和类型推导中尤为重要。

关键区别

4. const 与函数

const 在函数中的应用,是写出健壮接口的关键。

4.1 const 形参

像普通变量一样,函数内部不会修改形参时,可以用 const 修饰。但注意,在函数声明中,顶层 const 会被忽略:

void func(int val);          // 1
void func(const int val);    // 2 与 1 重复声明!顶层 const 被忽略

而对于指针和引用,底层 const 则有实质区别:

void func(int& val);         // 只能接受普通左值
void func(const int& val);   // 可以接受 const 或非 const 的左值/右值

使用 const & 作为参数是避免拷贝、同时保护原数据的最佳实践。

4.2 const 返回类型

返回一个 const 值类型通常没有意义(如 const int func()),因为调用者拷贝后本来就可以随便改。但它常用于返回指针或引用,防止调用者通过返回值修改内部数据。

class MyClass {
    int data;
public:
    const int& getData() const { return data; } // 返回底层 const 引用
};

5. const 成员函数:接口设计的精髓

这是面向对象中的重头戏。

语法:在成员函数参数列表后加 const 关键字。

class Widget {
private:
    int value;
public:
    int getValue() const {  // 常量成员函数
        // value = 10;      // 错误!不能修改任何非 mutable 成员变量
        return value;
    }
};

作用

  1. 承诺不修改对象状态:在函数体内,this 指针的类型是 const Widget* const,因此不能修改非 mutable 成员。
  2. 可被 const 对象调用const Widget w; w.getValue(); 是合法的。普通对象也可以调。
  3. 构成重载:可以根据成员函数是否为 const 来重载。
class Widget {
public:
    void display() { std::cout << "non-const\n"; }
    void display() const { std::cout << "const\n"; }
};
Widget w;
w.display();       // 调用普通版本
const Widget cw;
cw.display();      // 调用 const 版本

mutable 的妙用

如果一个 const 成员函数确实需要修改某个与对象逻辑状态无关的变量(如缓存、互斥锁),可将该变量声明为 mutable

class Cache {
    mutable int cachedValue;
    mutable std::mutex mtx;
public:
    int getValue() const {
        std::lock_guard<std::mutex> lock(mtx); // 可以在 const 函数内加锁
        if (cachedValue < 0) cachedValue = compute();
        return cachedValue;
    }
};

6. const 与迭代器

STL 迭代器与指针类似,也有 const 之分。

std::vector<int> vec = {1, 2, 3};
const std::vector<int>::iterator iter = vec.begin(); // 迭代器本身是 const
*iter = 10; // 可以修改所指元素
// ++iter;  // 错误,迭代器本身不可变
std::vector<int>::const_iterator cIter = vec.begin(); // 所指元素是 const
// *cIter = 10; // 错误,不能修改元素
++cIter;       // 可以,迭代器自身可变

需要元素不可变的遍历时,优先使用 cbegin()cend()

总结

const 是 C++ 类型系统中的一位“守夜人”:

掌握 const 不仅仅是记住语法,更重要的是形成“用 const 告诉编译器你的不变性约束”的思维习惯,这样才能写出更安全、更清晰的 C++ 代码。

希望这篇梳理对你有帮助,const 的世界很清晰,多写多练就不容易晕了。

一、基础概念题

1. const 变量必须在定义时初始化吗?为什么?

答案要点:必须初始化。因为 const 对象一旦创建,其值就不能再改变,若不初始化,它将永远拥有一个不确定的值。

2. const int 和 int const 有区别吗?

答案要点:没有区别,完全等价。当 const 修饰的是基本类型且没有指针参与时,位置不影响含义。

3. const 与 #define 定义常量有什么区别?

答案要点

二、指针与 const(必考,高频)

4. 解释 const int *p 和 int *const p 的区别。

答案要点

5. 以下代码错在哪?

int a = 10;
const int *p = &a;
int *q = p;   // 这行有什么问题?

答案要点:错误,p 是底层 const,q 是普通指针。如果把 p 赋给 q,就可以通过 *q 修改一个 const int 指向的对象,破坏了常量性。需要改为 const int *q = p; 或强制类型转换(不推荐)。

6. 判断对错并解释:

const int a = 10;
int *p = (int*)&a;
*p = 20;

答案要点:代码可能编译通过,但行为是未定义的a 本身是 const 对象,可能被放在只读内存区,强制修改会导致运行时崩溃或奇怪的优化行为。不要这样做。

三、顶层 const 与底层 const

7. 什么是顶层 const?什么是底层 const?各自在赋值时有什么影响?

答案要点

8. 给定代码,判断能否编译:

int i = 0;
const int ci = i;
const int *p1 = &ci;
int *const p2 = &i;
p1 = p2;      // (1)
p2 = p1;      // (2)
const int *const p3 = p2;  // (3)

答案要点

四、const 与函数

9. 这两个函数声明是否构成重载?为什么?

void f(int);
void f(const int);

答案要点:不构成重载,这是重复声明。顶层 const 在函数参数中被忽略,编译时会报重复定义。因为它们接受的实参类型没有区别。

10. 以下函数各自能接受什么类型的实参?

void f1(int&);
void f2(const int&);

答案要点

11. 返回 const 引用有什么意义?和返回值类型有什么区别?

答案要点

五、const 成员函数(高频)

12. 什么是 const 成员函数?它有什么作用?

答案要点

13. 简述 mutable 关键字的作用,并给出一个典型使用场景。

答案要点

14. 分析以下代码的输出:

class A {
public:
    void show() { cout << "non-const" << endl; }
    void show() const { cout << "const" << endl; }
};
int main() {
    A a;
    const A ca;
    a.show();
    ca.show();
    return 0;
}

答案要点:输出 non-constconst。const 对象调用 const 版本,非 const 对象优先调用非 const 版本。

15. const 成员函数中,this 指针的类型是什么?

答案要点const 类名* const。即指向常量对象的常量指针,因此不能通过 this 修改成员变量(mutable 除外)。

六、const 与迭代器

16. iterator 和 const_iterator 有什么区别?

答案要点

17. cbegin() / cend() 的作用是什么?

答案要点:无论容器本身是否为 const,都返回 const_iterator,便于编写只读遍历代码,增强安全性。

这些题目覆盖了 const 在面试中从基础到进阶的核心考察点,如果能全部清晰回答,const 这块基本就算过关了。

到此这篇关于C++ 的 const 相关知识点总结的文章就介绍到这了,更多相关C++ const内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文