【C++】const和static的用法

目錄

  • 🚀前言
  • 💻const:“只讀”的守護者
    • 💯修飾普通變量
    • 💯修飾指針
    • 💯修飾函數
    • 💯修飾類成員
    • 💯修飾對象
  • 🌟static:“靜態存儲”與“作用域控制”
    • 💯修飾全局變量
    • 💯修飾局部變量
    • 💯修飾類成員
      • 🎯static 成員變量
      • 🎯static成員函數
  • 💧const 與 static 結合應用
    • 💯關鍵用法:類內靜態常量的初始化
  • 🎋避坑指南
  • ??結尾總結

🚀前言

在這里插入圖片描述

大家好!我是 EnigmaCoder

  • 本文將分別介紹const與static的用法,最后介紹兩者的結合應用和常見坑點。

💻const:“只讀”的守護者

const 的核心作用是限制變量/對象的“可修改性”,強制編譯器檢查“意外修改”,本質是給代碼加“安全鎖”。它的用法圍繞“修飾誰”展開,不同修飾對象的含義完全不同,也是初學者最易踩坑的點。

💯修飾普通變量

  • 作用:變量初始化后不可修改,編譯期會檢查賦值操作。
  • 注意:必須在定義時初始化(局部/全局 const 均需)。
  • 示例:
    const int max_len = 10; // 正確:定義時初始化
    max_len = 20; // 錯誤:編譯器直接報錯,禁止修改
    

💯修飾指針

const修飾指針關鍵看 const* 的位置:

  • const int* pconst* 左邊):限制“指針指向的內容”不可改,指針本身可以換指向。
    int a = 5, b = 10;
    const int* p = &a;
    *p = 6; // 錯誤:指向的內容(a的值)不能改
    p = &b;  // 正確:指針可以指向新地址(b)
    
  • int* const pconst* 右邊):限制“指針本身”不可改,指向的內容可以改。
    int a = 5, b = 10;
    int* const p = &a;
    *p = 6; // 正確:指向的內容(a的值)可以改
    p = &b;  // 錯誤:指針不能換指向
    

💯修飾函數

  • 修飾函數參數:保證函數內部不修改參數(尤其針對引用/指針參數,避免意外篡改外部變量)。
    // 傳入字符串,僅讀取不修改,用 const 保護
    void printStr(const string& s) {s += "test"; // 錯誤:禁止修改 const 參數cout << s << endl; // 正確:僅讀取
    }
    
  • 修飾函數返回值:限制返回值不可被修改(常見于返回指針/引用的場景,避免外部篡改內部數據)。
    // 返回數組首地址,禁止外部修改數組內容
    const int* getArr() {static int arr[3] = {1,2,3};return arr;
    }
    int main() {const int* p = getArr();*p = 4; // 錯誤:返回值是 const,禁止修改
    }
    

💯修飾類成員

  • const 成員變量:屬于對象的“常量”,必須在構造函數初始化列表中初始化(不能在定義時直接賦值)。
    class Person {
    private:const int age; // const 成員變量
    public:// 正確:在初始化列表中初始化Person(int a) : age(a) {}// 錯誤:不能在構造函數體內賦值// Person(int a) { age = a; }
    };
    
  • const 成員函數:保證函數內部不修改任何非 mutable 成員變量,函數聲明和定義都要加 const
    class Person {
    private:int age;
    public:// 聲明時加 constvoid showAge() const;      //語法:返回值類型 函數名() const;
    };
    // 定義時也要加 const(位置不能錯)
    void Person::showAge() const {age = 20; // 錯誤:const 函數禁止修改成員變量cout << age << endl; // 正確:僅讀取
    }
    

💯修飾對象

const 修飾對象,本質是把對象變成 “只讀對象”—— 一旦定義,這個對象的成員變量就不能被修改,能有效保證數據安全(比如防止誤改關鍵數據)。

  • 格式很簡單:在對象定義前加const,和定義const變量(比如 const int a=10)的邏輯一致。
#include <iostream>
#include <string>
using namespace std;// 定義一個學生類
class Student {
public:string name;  // 成員變量:姓名int score;    // 成員變量:成績// 構造函數(初始化姓名和成績)Student(string n, int s) : name(n), score(s) {}// 普通成員函數:修改成績(可能改成員變量)void setScore(int s) {score = s;}// const 成員函數:只打印信息(不修改成員變量)void showInfo() const {cout << "姓名:" << name << ",成績:" << score << endl;}
};
int main() {// 1. 普通對象(可以修改成員,調用任意函數)Student s1("張三", 90); s1.score = 85;          // 允許:普通對象能改成員變量s1.setScore(88);        // 允許:普通對象能調用非const函數s1.showInfo();          // 允許:普通對象也能調用const函數// 2. const對象(只讀,核心限制:不能改成員,只能調const函數)const Student s2("李四", 85); // s2.score = 90;       // 錯誤!const對象不能直接修改成員變量// s2.setScore(92);     // 錯誤!const對象不能調用非const函數s2.showInfo();          // 允許!const對象只能調用const成員函數return 0;
}

遵循兩個規則:

  • const對象的成員變量絕對不能修改。
  • const對象只能調用const成員函數。

🌟static:“靜態存儲”與“作用域控制”

static 的核心是改變變量/函數的“存儲周期”或“作用域”,本質是管理“數據的生命周期”和“訪問范圍”,常見于“共享數據”“全局唯一”場景。

💯修飾全局變量

  • 作用:全局 static 變量的作用域僅限當前 .cpp 文件,避免不同文件中“同名全局變量”的命名沖突。
  • 對比普通全局變量:普通全局變量默認“跨文件可見”(用 extern 可引用),static 全局變量則“文件私有”。
  • 示例:
    // a.cpp
    static int global_val = 5; // 僅 a.cpp 可見// b.cpp
    extern int global_val; // 錯誤:無法引用 a.cpp 的 static 全局變量
    

💯修飾局部變量

  • 作用:局部 static 變量的“作用域”仍在函數內,但“存儲周期”是整個程序(僅初始化一次,函數調用結束后不銷毀)。
  • 典型場景:函數內的計數器、全局唯一的臨時數據。
  • 示例:
    void countCall() {static int cnt = 0; // 僅初始化一次(第一次調用時)cnt++;cout << "調用次數:" << cnt << endl;
    }
    int main() {countCall(); // 輸出 1countCall(); // 輸出 2(cnt 未被銷毀)
    }
    

💯修飾類成員

static 類成員是“所有對象共享的數據/方法”,不依賴具體對象存在。

🎯static 成員變量

  • 特點:屬于整個類,所有對象共用同一內存,必須在類外單獨初始化(不能在構造函數中初始化)。由于static成員變量存儲在類的外部,計算類的大小時不包含在內。
  • 示例:統計類的對象創建個數
    class Student {
    private:static int total; // 聲明:屬于 Student 類
    public:Student() { total++; } // 創建對象時計數+1~Student() { total--; } // 銷毀對象時計數-1// 必須用 static 函數訪問 static 變量(見下文)static int getTotal() { return total; }
    };// 類外初始化:不加 static,需指定類名
    int Student::total = 0;int main() {Student s1, s2;cout << Student::getTotal(); // 輸出 2(兩個對象)
    }
    

🎯static成員函數

  • 特點:沒有 this 指針(因為不依賴對象),只能訪問 static 成員變量/函數,不能訪問非 static 成員。
  • 調用方式:直接用“類名::函數名”調用(無需創建對象)。
  • 示例:上文 Student::getTotal(),直接通過類名調用。

💧const 與 static 結合應用

兩者結合的核心場景是“類的靜態常量”,即 static const(或 const static,兩者在類中等價),用于定義“類級別的常量”(所有對象共用,且不可修改),既實現了數據共享又達到了數據不可被改變的目的。

💯關鍵用法:類內靜態常量的初始化

  • C++11 及以后:static const 成員變量可在類內直接初始化(僅限字面量類型,如 int、char 等)。

  • 示例:

    class Config {
    public:// C++11+ 支持:類內直接初始化靜態常量static const int MAX_NUM = 100;static const string DEFAULT_NAME; // 非字面量類型,需類外初始化
    };// 非字面量類型的 static const 成員,仍需類外初始化
    const string Config::DEFAULT_NAME = "unknown";
    
  • 注意:C++11 前,static const 成員變量必須在類外初始化,即使是字面量類型。

🎋避坑指南

  1. 坑 1:const 變量能“強制修改”?
    用指針強制轉換可以修改 const 變量,但這是“未定義行為”(編譯器不報錯,但運行結果不可控,可能觸發崩潰),絕對禁止!

    const int a = 5;
    int* p = (int*)&a; // 強制轉換(危險!)
    *p = 10; // 運行時可能修改成功,但屬于未定義行為
    
  2. 坑 2:static 局部變量的線程安全?

    • C++11 及以后:static 局部變量的初始化是“線程安全”的(編譯器會加鎖,避免多線程同時初始化)。
    • C++11 前:非線程安全,多線程同時調用可能導致重復初始化。
  3. 坑 3:類 static 成員忘記類外初始化?
    僅在類內聲明 static 成員變量,未在類外初始化,會導致鏈接錯誤(編譯器找不到變量的定義)。記住:static 類成員“聲明在類內,定義在類外”。

??結尾總結

conststatic 雖基礎,但用法靈活,核心記住兩點:

  • const:圍繞“只讀”,為代碼加安全鎖,避免意外修改(重點分清修飾指針的兩種場景、類 const 成員的初始化)。
  • static:圍繞“靜態存儲/作用域”,管理數據生命周期(重點掌握類 static 成員的“類外初始化”和“共享特性”)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/100454.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/100454.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/100454.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

F019 vue+flask海外購商品推薦可視化分析系統一帶一路【三種推薦算法】

文章結尾部分有CSDN官方提供的學長 聯系方式名片 B站up&#xff1a; 麥麥大數據 關注B站&#xff0c;有好處&#xff01; 編號: F019 關鍵詞&#xff1a;海外購 推薦系統 一帶一路 python 視頻 VueFlask 海外購電商大數據推薦系統源碼 &#xff08;三種推薦算法 全新界面布局…

【大數據專欄】流式處理框架-Apache Fink

Apache Fink 1 前言 1.1 功能 1.2 用戶 國際 國內 1.3 特點 ◆ 結合Java、Scala兩種語言 ◆ 從基礎到實戰 ◆ 系統學習Flink的核心知識 ◆ 快速完成從入門到上手企業開發的能力提升 1.4 安排 ◆ 初識Flink ◆ 編程模型及核心概念 ◆ DataSet API編程 ◆ Data…

向內核社區提交補丁

一、背景 內核的版本一直以來一直在持續迭代&#xff0c;離不開眾多開發者的貢獻。有時候我們會根據項目要求基于現有的內核版本開發一些新的功能或者修復掉一些特定場下的問題&#xff0c;我們是可以將其提交給社區的。 一般提交社區有兩個基本原則&#xff0c;一是提交的補…

TENGJUN-USB TYPE-C 24PIN測插雙貼連接器(H14.3,4腳插板帶柱):USB4.0高速傳輸時代的精密連接方案解析

在高速數據傳輸與多設備互聯需求日益增長的當下&#xff0c;USB TYPE-C接口憑借其可逆插拔、高兼容性的優勢成為主流&#xff0c;而TENGJUN推出的USB TYPE-C 24PIN測插雙貼連接器&#xff08;規格&#xff1a;H14.3&#xff0c;4腳插板帶柱&#xff09; &#xff0c;以對USB4.0…

企業級 Docker 應用:部署、倉庫與安全加固

1 Docker簡介及部署方法 1.1 Docker簡介 Docker之父Solomon Hykes&#xff1a;Docker就好比傳統的貨運集裝箱 Note 2008 年LXC(LinuX Contiainer)發布&#xff0c;但是沒有行業標準&#xff0c;兼容性非常差 docker2013年首次發布&#xff0c;由Docker, Inc開發1.1.1 什么是do…

rust語言 (1.88) 學習筆記:客戶端和服務器端同在一個項目中

同一項目下多個可執行文件&#xff0c;多個子項目參照以下&#xff1a; 一、項目目錄 項目/|-- client/|-- main.rs|-- Cargo.toml|-- server/|-- main.rs|-- Cargo.toml|-- Cargo.toml二、項目公共 Cargo.toml [workspace] # 定義Rust工作區配置 members …

mac本地安裝mysql

本人環境 macOs 14.5 1.下載安裝mysql https://dev.mysql.com/downloads/mysql/ 配置環境變量&#xff0c;打開terminal vim ~/.bash_profile 添加MYSQL_HOME/usr/local/mysql 在PATH中添加 通過mysql --version命令查看版本 2.開啟mysql 打開終端teminal,輸入命令 sudo…

面試前端遇到的問題

面試官讓我寫一個delay函數然后這是我寫的代碼async function delay(){setTimeout(function() {}, 3000); }面試官就和我說不是這個&#xff0c;用promise當時就蒙了&#xff0c;什么東西&#xff0c;為什么要用promise然后問豆包說Promise 是 JavaScript 中用于處理異步操作的…

Ubuntu Desktop 22.04.5 LTS 使用默認的 VNC 遠程桌面

1. 打開 VNC 打開設置 - 分享 - 遠程桌面2. 配置 VNC 打開遠程桌面 啟用vnc 選擇vnc密碼訪問 配置密碼3. 固定密碼 遠程桌面的訪問密碼在每次開機后會刷新一次&#xff0c;可以通過以下方式固定 打開【應用程序】&#xff0d;【附件】&#xff0d;密碼和加密密鑰&#xff08;或…

【無線安全實驗4】基于偽隨機數的WPS PIN碼逆向(精靈塵埃/仙塵攻擊)

文章目錄1 原理分析1.1 WPS連接過程1.1.1 初始階段1.1.2 注冊階段1.2 WPS攻擊原理1.2.1 在線攻擊1.2.2 離線攻擊1.2.2.1 Ralink模式1.2.2.2 eCos模式2 實驗過程3 參考資料在2011年 Stefan Viehbck 演示過WPS的在線暴力攻擊&#xff0c;由于PIN碼猜測最多只需11000種組合&#x…

IDEA開發過程中經常使用到的快捷鍵

IntelliJ IDEA 開發 Java 時常用的快捷鍵列表 代碼編輯與行操作快捷鍵功能描述Ctrl Y刪除當前行。Ctrl D復制當前行到下一行。Shift Alt ↑將當前行&#xff08;或選中塊&#xff09;向上移動。Shift Alt ↓將當前行&#xff08;或選中塊&#xff09;向下移動。Ctrl /注…

ubuntu使用webrtc庫開發一個webrtc推拉流程序

目錄 一. 前言 二. 整體交互流程 三. 類實現說明 1. WebRtcClient 2. SignalPeerClient 3. WebRTCStream 4. 視頻源類 5. 拉流渲染 四. 使用示例 1. 推流代碼示例 2. 拉流代碼示例 一. 前言 在 《ubuntu編譯webrtc庫》我們介紹了如何在 ubuntu 上使用 webrtc 源代碼…

【Block總結】ConverseNet:神經網絡中的反向卷積算子

1. 論文信息 標題:Reverse Convolution and Its Applications to Image Restoration 發布平臺:arXiv 論文鏈接:https://arxiv.org/pdf/2508.09824 代碼倉庫:https://github.com/cszn/converseNet 任務領域:圖像恢復(去噪、超分辨率、去模糊) 核心貢獻:提出了一種新的反…

優化瀏覽體驗:4個設置讓Google Chrome更好用!

想要更流暢、更快速的瀏覽體驗嗎&#xff1f;本文章將向大家展示Google Chrome中你應該立即更改的4個重要設置&#xff0c;設置調整將幫助您提升性能&#xff0c;讓你的瀏覽更高效。1、打開瀏覽器&#xff0c;在地址欄輸入“chrome://flags"確定&#xff0c;在搜索標志中輸…

【Git】一篇文章帶你入門Git

1. 初識 Git 1.1 Git 是什么&#xff1f; Git 是一個開源的分布式版本控制系統&#xff0c;用于高效地跟蹤和管理項目代碼的變更歷史&#xff08;不僅僅是代碼&#xff0c;還有其它格式也是可以的~&#xff09; 1.2 為什么要有 Git 在學習或者是工作的時候&#xff0c;比如…

8 基于機器學習進行遙感影像的地物分類-以隨機森林為例

目錄 1 讀取數據 2 數據預處理 3 模型訓練 4 精度分析 5 模型預測 1 讀取數據 1.右鍵數據所在文件夾,用pycharm打開為項目 2.在settings中設置python環境為先前配置的帶GDAL和sklearn的環境 3.新建一個文件夾命名為code來存放代碼,在code文件夾中新建一個rfc.py

極簡版 Nginx 反向代理實驗步驟

以下是最核心的反向代理實現步驟&#xff0c;專注于 “客戶端→Nginx 代理→后端服務” 的基礎轉發功能&#xff1a;一、準備 2 臺服務器角色IP 示例需安裝軟件代理服務器192.168.1.10Nginx后端服務器192.168.1.11Nginx/Apache二、后端服務器配置&#xff08;192.168.1.11&…

Windsurf 插件正式登陸 JetBrains IDE:讓 AI 直接在你的 IDE 里“打工”

那天你說,我們可以永遠在一起——成了我聽到的最高興的,而后知后覺的謊言。 而今天,AI 說:“我可以幫你寫完這段代碼。” —— 這才是真正的“永遠在一起”。 最近,AI 編程工具賽道迎來一場“潛行式革命”:Windsurf Wave 7 正式發布 JetBrains IDE 插件版本,徹底打破“A…

188. Java 異常 - Java 異常處理規范

文章目錄188. Java 異常 - Java 異常處理規范&#x1f4dc; 什么是“Catch or Specify Requirement”&#xff1f;? 兩種滿足方式方法一&#xff1a;使用 try-catch 捕獲異常方法二&#xff1a;使用 throws 聲明異常? 不遵守規則會怎樣&#xff1f;&#x1f4a1; 哪些異常必須…

泛型通配符 T、E、K、V、?

在Java后端開發中&#xff0c;你一定在寫集合類或工具類時&#xff0c;見過 T、E、K、V、? 這樣的泛型通配符。但你是否有過以下疑惑&#xff1a; T、E、K、V 到底有什么區別&#xff1f;為什么大家都用這些字母&#xff1f;List<?> 和 List 有什么不同&#xff1f;什么…