【C++基础】Day 2:关键字之 const 与 static

目录

学习日志|Day 2

一、const 关键字

1. 简要回答

2. 详细回答

3. 图表总结

4. 示例代码

5. const 关键字总结

6.面试一句话总结

二、static 关键字

1. 简要回答

2. 详细回答

1) 静态变量(包含:全局静态变量、静态局部变量)

(1)全局静态变量(static int g;)

(2)静态局部变量(static int local;)

2)静态成员变量(static int ExampleClass::staticVar;)

3)静态成员函数(static void staticMethod();)

4)静态函数(类外,文件内 static 函数)

5)静态函数 和 静态成员函数对照

3. 图表总结

1)按“作用对象”分类

2)“是否和对象相关”

4. 示例代码

1)静态函数:只能本文件使用(模块级封装)

2)静态成员函数:属于类,无需对象

3)静态局部变量:计数器例子

5. 知识拓展(面试回答加分点)

1)static 和 多线程

2)static 成员和单例模式

3)static 和 链接属性(内部链接)

4)static 成员的初始化顺序问题(跨源文件)

6. 面试一句话总结


学习日志|Day 2

第二篇文章主要梳理了以下关键字的高频考点:
const  /  static 


一、const 关键字

(含指针常量 / 常量指针 / const 成员函数 / const 引用)

关于 const 的详细用法,可以查看我之前的笔记记录:

C++ 变量作用域 & 存储期 & 链接性:const / static / extern 全面解析-CSDN博客https://blog.csdn.net/m0_58954356/article/details/154607017?spm=1001.2014.3001.5502C++ 指针与引用全面解析:const 修饰三种形式 + 底层机制 + 八股总结_const 引用 的几种情况-CSDN博客https://blog.csdn.net/m0_58954356/article/details/154637648?spm=1001.2014.3001.5502C++ 常量与 const —— #define vs const 全面对比详解-CSDN博客https://blog.csdn.net/m0_58954356/article/details/154655036?spm=1001.2014.3001.5502


1. 简要回答

  • const = 只读语义

  • 顶层 const:修饰指针本身 → 指针不能改地址

  • 底层 const:修饰指向对象 → 不能通过指针改值

  • const 成员函数不能修改成员变量

  • const 引用防止函数内部修改传参


2. 详细回答

  1. *常量指针(int const p) → 顶层 const

    • 指针本身不可变

    • 可修改指向对象的值

    • 声明形式:int *const ptr = &some_int_var;

  2. *指向常量的指针(const int p) → 底层 const

    • 指针可变

    • 不能通过 p 修改值

    • 声明形式:const int *ptr = &some_const_int_var

  3. const 引用

    • 绑定临时变量

    • 防止修改

  4. const 成员函数

    • 隐含 this = const T* const this

    • 不能修改成员(除 mutable)


3. 图表总结

声明含义能否改指针能否改值
const int *p指向常量的指针
int *const p常量指针
const int *const p指向常量的常量指针
int const *p与 const int* 相同

4. 示例代码

// 1. 常量变量
const int a = 10;
// a = 20;  // ❌ 错误:a 是常量,不能修改



// 2.指向常量的指针(pointer to const)
int x = 10, y = 20;
const int* p = &x;  // 指向常量的指针(底层 const)
p = &y;        // ✔ 指针能改
//*p = 30;     // ❌ 无法修改 *p


// 3.常量指针(const pointer)
int x = 10;
int* const p = &x;  // 常量指针(顶层 const)
*p = 99;     // ✔ 修改值
//p = &y;     // ❌ 指针不能改地址


// 4.常量引用(const reference)
int x = 10;
const int& r = x;   // 常量引用
// r = 20;          // ❌ 不能改
// r++;             // ❌ 不能改


// 5.const 成员函数(class A::func() const)
class A {
public:
    int val = 0;

    int get() const {  
        // val = 10;  // ❌ 不允许修改对象
        return val;   //  ✔ 读取没问题
    }

    void set(int v) {
        val = v;  //     ✔ 普通成员函数可以修改成员
    }
};

int main() {
    A obj;
    obj.set(100);   // ✔ 普通对象能调普通函数
    obj.get();      // ✔ 普通对象能调 const 函数

    const A obj2;   //  关键!
    // obj2.set(10);  ❌ const 对象不能调用非 const 函数
    obj2.get();       // ✔ const 对象只能调用 const 函数
}


5. const 关键字总结

  1. 常量变量:声明常量,使变量的值不能被修改。
  2. 指针和引用:声明指向常量的指针,表示指针所指向的值是常量,不能通过指针修改。声明常量引用,表示引用的值是常量,不能通过引用修改。
const int* ptr = &constantValue;  // 指向常量的指针
const int& ref = constantValue;  // 常量引用
  1. 成员函数:用于声明常量成员函数,表示该函数不会修改对象的成员变量(对于成员变量是非静态的情况)。

  2. 常量对象:声明对象为常量,使得对象的成员变量不能被修改。

  3. 常引用参数:声明函数参数为常量引用,表示函数不会修改传入的参数。

  4. 常量指针参数:声明函数参数为指向常量的指针,表示函数不会通过指针修改传入的数据。

  5.  const 对象只能调用 const 成员函数,因为 const 成员函数保证不会修改对象状态。
    普通成员函数可能修改对象状态,因此被 const 对象禁止调用。


6.面试一句话总结

  • const 的作用是提供只读保护,它可以修饰变量、指针、引用、对象和成员函数。
  • 变量加 const 表示值不能改;
  • const int* 是指向常量的指针(不能改值但能换指向);
  • int* const 是常量指针(能改值但不能换指向);两者都加 const 是指向常量的常量指针,都不能改;
  • const 引用常用于函数参数,既避免拷贝又保证不修改传入对象;
  • 把对象声明为 const 后,它只能调用 const 成员函数,因为 const 成员函数的 this 是 const T* const,承诺不修改对象状态。

总结来说:

const 通过“顶层/底层 const”机制给 C++ 提供了完整的只读体系,使代码更安全、更易优化。



二、static 关键字


1. 简要回答

static:延长生命周期(全局数据区)、限制可见性(内部链接)、在类中实现共享(静态成员变量)和无 this 的类函数(静态成员函数)。


2. 详细回答

1) 静态变量(包含:全局静态变量、静态局部变量)

(1)全局静态变量(static int g;
  • 定义在函数外、文件作用域,用 static 修饰的全局变量。

  • 生命周期:程序开始到程序结束(和普通全局变量一样)。

  • 作用域当前源文件可见,其他文件不能通过 extern 访问到

  • 存储位置:全局/静态存储区。

  • 作用:隐藏实现细节,避免全局变量“污染”整个工程的符号表(内部链接)。

(2)静态局部变量(static int local;
  • 定义在函数内,用 static 修饰的局部变量。

  • 生命周期:程序开始到结束(不会因为函数返回而销毁)。

  • 作用域:仅当前函数内可见

  • 特点

    • 只初始化一次(第一次执行到定义处时初始化)。

    • 后续调用保留上一次的值,很适合做“记数器”、“缓存”。


静态局部变量在第一天的全局变量/静态局部变量/局部变量中进行的详细的讲解。以下是链接:

【C++基础】Day 1:全局/静态/局部变量、指针 vs 引用、整型类型-CSDN博客https://blog.csdn.net/m0_58954356/article/details/154984198?spm=1001.2014.3001.5501


2)静态成员变量(static int ExampleClass::staticVar;

  • 定义在类内、用 static 修饰的成员变量

  • 不属于某个对象,而是属于整个类:所有对象共享一份。

  • 静态成员变量必须在类外部单独定义,以便为其分配存储空间

class ExampleClass {
public:
    static int staticVar;  // 静态成员变量声明
};

// 静态成员变量定义
int ExampleClass::staticVar = 0;
  • 生命周期:程序整个运行期间。

  • 用途

    • 用来统计“类一共创建了多少对象”;

    • 用来做类级的配置、缓存等。


3)静态成员函数(static void staticMethod();

  • 类内部用 static 关键字修饰的成员函数是静态成员函数

  • 没有 this 指针

    • 不能访问普通成员变量/函数(因为没有具体对象)。

    • 只能访问静态成员变量/静态成员函数。

  • 调用方式

    • 可以用类名直接调用ExampleClass::staticMethod( ),而不需要创建类的实例

class A {
public:
    static void foo() {
        cout << "I am class-level function" << endl;
    }
};

本质:

“写在类里的普通函数”,只不过用类作为命名空间 + 可以访问类的静态数据


4)静态函数(类外,文件内 static 函数)

  • 文件作用域(全局区) 使用 static 修饰的函数
static void helper() {
    cout << "I am file-local" << endl;
}
  • 限制函数只在当前 .cpp 文件内可见(内部链接)

        其他文件无法 extern 引用它

        常用于隐藏库内部实现,避免全局符号污染


5)静态函数 和 静态成员函数对照

对比项静态函数(static function)静态成员函数(static member function)
语言层级C / C++C++(类)
作用域文件作用域类作用域
可见性仅当前文件可见类内可见,通过类名访问
是否属于对象❌ 不属于对象❌ 不属于对象(属于类)
是否有 this❌ 无 this❌ 无 this
调用方式仅当前文件内调用类名::函数 或 对象.函数
是否能访问普通成员变量❌ 不能❌ 不能(因为没 this)
是否常与静态成员变量搭配❌ 不相关✔ 常一起使用
用途隐藏函数(模块内实现)类级工具函数、管理静态成员变量

3. 图表总结

1)按“作用对象”分类

用法代码例子作用对象生命周期作用域 / 可见性
全局静态变量static int g;变量整个程序当前源文件内
静态局部变量static int x;(在函数内)变量整个程序当前函数内
静态成员变量static int Example::cnt;类共享变量整个程序类内访问(但存储在类外)
静态成员函数static void foo();类级函数(无 this)程序整个期类内/类名可调用
文件内静态函数static void helper();函数符号由编译单元决定当前源文件

2)“是否和对象相关”

是否依赖对象用法说明
依赖对象普通成员变量 / 成员函数需要对象,有 this
不依赖对象静态成员变量 / 静态成员函数属于类级别,无 this

4. 示例代码

1)静态函数:只能本文件使用(模块级封装)

//  a.cpp

static void helper() {   // 外部文件看不到
    cout << "helper" << endl;
}

void api() {
    helper();  // OK
}
//  b.cpp

extern void helper();  // ❌ 链接失败:helper 是内部链接

静态函数 = 隐藏在当前 .cpp 内部的工具函数。


2)静态成员函数:属于类,无需对象

class Math {
public:
    static int add(int a, int b) {
        return a + b;
    }
};

// 调用
int x = Math::add(1, 2);

常用于提供“类级工具函数”,如数学函数、配置设置等。


3)静态局部变量:计数器例子

#include <iostream>
using namespace std;

void foo() {
    static int count = 0;  // 只初始化一次
    count++;
    cout << "foo called " << count << " times\n";
}

int main() {
    foo(); // 1
    foo(); // 2
    foo(); // 3
}

说明:count 不会随着 foo() 返回而销毁,每次调用都会在上次基础上累加。


5. 知识拓展(面试回答加分点)

1)static 和 多线程

  • 静态局部变量、静态成员变量在多线程环境下是共享的,需要考虑加锁。

  • C++11 之后,函数内的 static 局部变量初始化是线程安全的

static Example instance;  // 第一次调用时安全初始化(C++11)

2)static 成员和单例模式

单例模式常用:

class Singleton {
public:
    static Singleton& instance() {
        static Singleton inst; // 函数内 static,懒汉模式 + 线程安全初始化
        return inst;
    }
private:
    Singleton() {}
};

这里用到了两个 static:

  • 静态局部变量:确保只创建一次对象

  • 静态成员函数:作为全局访问入口


3)static 和 链接属性(内部链接)

  • static 修饰全局变量 / 函数 → 内部链接(只能在当前翻译单元中使用)。

  • 不使用 static → 外部链接(可通过 extern 在其他文件访问)。

这个是 C/C++ 链接模型的基础概念,面试官问到“static 函数和普通函数区别?”时可以提一句:

“static 全局函数是内部链接,只在当前文件可见,常用于隐藏实现细节。”


4)static 成员的初始化顺序问题(跨源文件)

  • 不同源文件中的 static 全局变量的初始化次序是未定义的

  • 避免在一个 static 对象的构造中依赖另一个源文件的 static 对象(著名的“静态初始化顺序问题”)。

  • 解决方案:用函数内 static(“懒汉式单例”)替代全局 static 对象。


6. 面试一句话总结

  • static 的作用是控制变量/函数的生命周期和可见性,并在类里提供类级共享。
  • 用在局部变量上时,会把变量的生命周期延长到整个程序且只初始化一次;
  • 用在全局变量和全局函数上时,会把可见性限制在当前源文件,实现内部链接,用于隐藏实现;
  • 用在类中修饰成员变量时,使所有对象共享一份数据;
  • 用在类中修饰成员函数时,使其成为无 this 指针的类级函数,只能访问静态成员。

总结来说,static = “延长生命周期 + 限制可见范围 + 提供类级共享”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值