当前位置: 首页 > news >正文

C/C++ 关键关键字面试指南 (const, static, volatile, explicit)

目录

1. const (常量)

核心用法与考点:

1.1 修饰变量和指针

1.2 修饰函数参数和返回值

1.3 修饰类成员函数(C++ 特有)

1.4 代码示例:

2. static (静态)

核心用法与考点:

2.1 修饰局部变量(改变存储期)

2.2 修饰全局变量和函数(改变链接性)

2.3 修饰类成员变量(C++ 特有)

2.4 修饰类成员函数(C++ 特有)

2.5 代码示例:

3. volatile (易失性)

核心用法与考点:

3.1 阻止编译器优化

3.2 常见应用场景:

3.3 与 const 的结合

4. explicit (显式)

核心用法与考点:

4.1 修饰单参数构造函数

4.2 修饰转换函数(C++11/14)


1. const (常量)

定义: 用于声明常量或指定不允许修改的数据。它强制执行“常量正确性”(Const Correctness),是 C++ 中提高代码健壮性和可读性的核心机制。

核心用法与考点:

1.1 修饰变量和指针

理解 const 靠近谁,谁就是常量。

声明方式

含义

可修改性

const int a = 10;

常量整数

a 的值不可改

const int* p;

指向常量的指针

*p (值)不可改,p (地址)可改

int* const p;

常量指针

*p (值)可改,p (地址)不可改

const int* const p;

指向常量的常量指针

*pp 都不可改

1.2 修饰函数参数和返回值
  • 修饰参数: 使用 const 引用 (const T&) 传递对象,可以避免不必要的拷贝(效率高),同时保证函数内不会修改原始对象(安全性高)。

  • 修饰返回值: 限制调用者不能修改返回的对象。

1.3 修饰类成员函数(C++ 特有)

在成员函数末尾加上 const,表示该函数是一个 常成员函数

  • 常成员函数不能修改类的任何非 static 成员变量(除非该成员被声明为 mutable)。

  • 常对象只能调用常成员函数。

1.4 代码示例:
#include <iostream>
#include <vector>//-------------------------------------------
// 1.1  const 修饰变量 / 指针
//-------------------------------------------
void demo_pointer() {int x = 5, y = 10;const int a = 42;      // a 只读// a = 43;             // ❌ 编译错误:a 是常量const int* p1 = &x;    // *p1 只读,p1 可改// *p1 = 100;          // ❌ 不能改指向的值p1 = &y;               // ✅ 可以改指向int* const p2 = &x;    // p2 只读,*p2 可改*p2 = 100;             // ✅ 可以改值// p2 = &y;            // ❌ 不能改指针本身const int* const p3 = &x; // 全只读// *p3 = 200;  p3 = &y; // ❌ 都动不了
}//-------------------------------------------
// 1.2  const 修饰函数参数 & 返回值
//-------------------------------------------
// 参数:大对象只读传参,零拷贝又安全
void printVec(const std::vector<int>& v) {  // v 只能读// v.push_back(9);      // ❌ 编译错误:v 是 constfor (int n : v) std::cout << n << ' ';std::cout << '\n';
}// 返回值:阻止调用者改临时量
const int getMax(const int& a, const int& b) {return (a > b ? a : b);
}//-------------------------------------------
// 1.3  const 成员函数
//-------------------------------------------
class Counter {int value_ = 0;mutable int access_ = 0;   // mutable 允许在 const 函数里改
public:int get() const {          // ① 常成员函数++access_;             // ✅ mutable 成员可改return value_;}void inc() { ++value_; }   // 普通函数可改成员// 重载:const / 非 const 版本int& data()       { return value_; } // 非 const 对象调用const int& data() const { return value_; } // const 对象调用
};int main() {demo_pointer();std::vector<int> nums{1, 2, 3};printVec(nums);              // 1 2 3int m = getMax(3, 7);std::cout << "max=" << m << '\n';  // max=7// getMax(3,7) = 99;         // ❌ 返回的是 const int,不能当左值Counter c1;c1.inc();std::cout << "c1=" << c1.get() << '\n'; // 1const Counter c2;            // ② 常对象// c2.inc();                 // ❌ 只能调 const 成员函数std::cout << "c2=" << c2.get() << '\n'; // 0// c2.data() = 5;            // ❌ 返回 const int&,不能赋值
}

4 句话再总结

  1. const 靠谁,谁只读;靠 * 左边还是右边,决定“值”还是“指针”只读。

  2. const T& 传参 = 零拷贝 + 防篡改,是 C++ 最常用签名。

  3. 成员函数末尾加 const = 隐式 this 指针前加 const,内部不能改普通成员。

  4. 常对象只能调常成员函数;需要统计/缓存时用 mutable 打洞。

2. static (静态)

定义: static 关键字改变了变量或函数的存储期(Storage Duration)、作用域(Scope)和链接性(Linkage)。

核心用法与考点:

2.1 修饰局部变量(改变存储期)
  • 作用: 局部变量的生存期从函数调用结束延伸到整个程序运行期间。

  • 特点: 只初始化一次。

2.2 修饰全局变量和函数(改变链接性)
  • 作用: 将全局变量或函数的外部链接性(External Linkage)改为 内部链接性(Internal Linkage)。

  • 特点: 它们只能在当前文件(编译单元)内访问和使用,对其他文件隐藏。这有助于避免命名冲突。

2.3 修饰类成员变量(C++ 特有)
  • 作用: 静态成员变量 属于整个类,而不是任何特定的对象。

  • 特点: 整个类只有一个副本,所有对象共享。必须在类外进行定义和初始化。

2.4 修饰类成员函数(C++ 特有)
  • 作用: 静态成员函数 属于整个类,不接收隐式的 this 指针。

  • 特点: 静态成员函数只能直接访问类的静态成员(变量和函数),不能访问非静态成员。

2.5 代码示例:
 
//============ file: main.cpp ============
#include <iostream>//----------------------------------------
// 2.2 全局 static:内部链接,别的文件看不到
//----------------------------------------
static int g_hidden = 999;          // 只在 main.cpp 有效
static void hiddenFunc() {          // 同上,链接器对外“隐藏”std::cout << "hiddenFunc: " << g_hidden << '\n';
}//----------------------------------------
// 2.1 局部 static:存储期变成“整个程序运行期”
//----------------------------------------
void visitCount() {static int count = 0;           // ① 只有第一次进来才初始化++count;std::cout << "第 " << count << " 次调用 visitCount\n";
}//----------------------------------------
// 2.3 + 2.4 类静态成员
//----------------------------------------
class Logger {
public:// 非静态成员:每个对象各一份std::string name_;// 静态数据成员:整个类只有一份,必须类外再定义一次static int instanceCount;       // ② 只是“声明”,不是“定义”// 静态成员函数:没有 this,只能访问静态成员static void printCount() {std::cout << "当前实例总数 = " << instanceCount << '\n';// std::cout << name_;      // ❌ 编译错误:没有 this,不能访问非静态成员}// 构造函数:每创建一个对象就 ++explicit Logger(const std::string& n) : name_(n) {++instanceCount;}// 析构函数:对象销毁就 --~Logger() { --instanceCount; }
};// ② 类静态数据成员的“真正定义”放在类外(只能有一次)
int Logger::instanceCount = 0;//============ main 函数:演示全部效果 ============
int main() {std::cout << "----- 局部 static -----\n";visitCount();   // 第 1 次visitCount();   // 第 2 次visitCount();   // 第 3 次std::cout << "\n----- 全局 static -----\n";hiddenFunc();   // 能调到,因为同文件std::cout << "\n----- 类 static -----\n";Logger::printCount();           // 0 ,还没有对象{Logger a("A");Logger::printCount();       // 1Logger b("B");Logger::printCount();       // 2}                               // a、b 析构Logger::printCount();           // 0  再次回到 0// 不需要对象,直接类名调用静态函数Logger::printCount();
}

4 句话再总结

  1. 局部 static 让变量跨越函数调用继续存活。

  2. 全局 static 让名字跨不出当前源文件

  3. 类静态数据成员只有一份,类外必须再定义一次

  4. 类静态成员函数没有 this,只能玩静态成员,调用时可以不要对象

3. volatile (易失性)

定义: 用于告诉编译器,变量的值可能会在程序控制流之外被意外地修改(即“易失”)。

核心用法与考点:

3.1 阻止编译器优化

当编译器看到一个变量的值在两次使用之间没有被程序修改时,它可能会进行优化,将该值缓存在 CPU 寄存器中,而不是每次都从内存中重新读取。

  • 用途: volatile 关键字指示编译器,每次访问该变量时都必须从 内存 中重新读取它的值,而不是使用寄存器中的缓存值。

3.2 常见应用场景:
  1. 并行设备(硬件): 访问内存映射的 I/O 寄存器,这些寄存器的值可能被外部硬件改变。

  2. 中断服务程序(ISR): 全局变量被 ISR 和主程序同时访问。

  3. 多线程环境(并发): 多个线程共享的全局变量(注意:volatile 本身不能解决竞态条件,仍需要互斥锁等同步机制,但它是第一道防线)。

示例:

// 假设 status 寄存器的值可能被硬件修改
volatile int status_register;void wait_for_hardware() {// 如果没有 volatile,编译器可能优化为只读一次 status_registerwhile (status_register == 0) {// 等待硬件设置 status_register 为非零值}
}
3.3 与 const 的结合
  • volatile const int READ_ONLY_REG;:表示这是一个不能被程序修改的常量(const),但它可能会被外部硬件修改(volatile)。

4. explicit (显式)

定义: (C++ 特有) 用于修饰类的构造函数或转换函数,以禁止(抑制)编译器进行隐式的类型转换。

核心用法与考点:

4.1 修饰单参数构造函数
  • 问题: 如果一个类有一个只接受一个参数的构造函数,C++ 允许编译器使用这个构造函数将参数类型隐式转换为类类型。

  • 解决方案: 使用 explicit 关键字可以避免这种不期望的隐式转换。

示例:

class Data {
public:// 没有 explicit:允许隐式转换Data(int x) { /* ... */ } // 使用 explicit:禁止隐式转换// explicit Data(int y) { /* ... */ } 
};void process(Data d) { /* ... */ }// 如果构造函数没有 explicit:
Data d1 = 10;     // 允许:隐式调用 Data(10)
process(20);      // 允许:隐式调用 Data(20)// 如果构造函数使用了 explicit:
// Data d1 = 10;  // 错误:禁止隐式转换
Data d2(30);      // 允许:显式调用
process(Data(40)); // 允许:显式构造临时对象
4.2 修饰转换函数(C++11/14)

explicit 也可以修饰自定义类型转换操作符(如 operator bool()),防止对象被隐式转换为目标类型。

总结: explicit 关键字提高了代码的清晰度和安全性,防止在不经意间发生类型转换,从而避免潜在的 bug。

http://www.dtcms.com/a/431822.html

相关文章:

  • 网络IO基础知识
  • 基于ollama运行27b gemma3解决ffmpeg命令生成问题
  • 银河麒麟Kylin-Server-V10
  • 昆明云南微网站搭建张家界网站建设dcwork
  • 正则表达式匹配 - 动态规划
  • Java 开发工具,最新2025 IDEA 使用
  • 动态规划 - 背包详解(下)
  • 北京小程序定制开发seo技能培训课程
  • 个人网站设计内容和要求企业做网站带来的好处
  • 关于校园图书馆网站建设公司设计图
  • 怎么样用自己电脑做网站企业注册信息查询单
  • 自己怎么做家政网站做百科需要发哪些网站
  • 网站开发需要哪些资料wordpress主题黑糖
  • 丽江市网站建设制作aspnet网站开发实例教程pdf
  • 添加Entity Framework Core
  • 中小企业加盟网站建设精品建站教程
  • 凡科建设网站入门版好不青木三色品牌商城网站开发
  • 波峰焊万用治具的制作及使用
  • 怎样在手机上创建网站班级网站首页怎么做
  • 拖鞋设计网站推荐做室内概念图的网站
  • 公司建一个网站昆明seocn整站优化
  • Claude Sonnet 4.5重磅发布:Claude Sonnet 4.5新特性大全|更新了什么?
  • 想做个卷帘门百度优化网站网站的版面布局
  • 网站开发实战视频教程广州 骏域网站建设 陶瓷
  • 国内开源建站cms网站注销主体注销
  • 网站开发相关书籍资料5台电脑做视频网站服务器
  • AI赋能千行百业:金融、医疗、教育、制造业的落地实践与未来展望
  • 漳州专业做网站国家开发银行学生在线系统
  • python 网站开发 前端wordpress开发平台
  • 怎样在国外网站购买新鲜橙花做纯露建筑网站排行