欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++之const和static的使用及說明

 更新時(shí)間:2025年09月18日 08:56:38   作者:EnigmaCoder  
C++中const與static的用法:const限制變量/對(duì)象只讀性,確保數(shù)據(jù)安全;static控制變量/函數(shù)的存儲(chǔ)周期與作用域,實(shí)現(xiàn)數(shù)據(jù)共享,兩者結(jié)合的static const用于定義類級(jí)常量,需注意const變量不可強(qiáng)制修改、static局部變量線程安全問題及類static成員必須類外初始化的要點(diǎn)

本文將分別介紹const與static的用法,最后介紹兩者的結(jié)合應(yīng)用和常見坑點(diǎn)。

const:“只讀”的守護(hù)者

const 的核心作用是限制變量/對(duì)象的“可修改性”,強(qiáng)制編譯器檢查“意外修改”,本質(zhì)是給代碼加“安全鎖”。

它的用法圍繞“修飾誰”展開,不同修飾對(duì)象的含義完全不同,也是初學(xué)者最易踩坑的點(diǎn)。

修飾普通變量

  • 作用:變量初始化后不可修改,編譯期會(huì)檢查賦值操作。
  • 注意:必須在定義時(shí)初始化(局部/全局 const 均需)。

示例:

const int max_len = 10; // 正確:定義時(shí)初始化
max_len = 20; // 錯(cuò)誤:編譯器直接報(bào)錯(cuò),禁止修改

修飾指針

const修飾指針關(guān)鍵看 const* 的位置:

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

修飾函數(shù)

修飾函數(shù)參數(shù):保證函數(shù)內(nèi)部不修改參數(shù)(尤其針對(duì)引用/指針參數(shù),避免意外篡改外部變量)。

// 傳入字符串,僅讀取不修改,用 const 保護(hù)
void printStr(const string& s) {
    s += "test"; // 錯(cuò)誤:禁止修改 const 參數(shù)
    cout << s << endl; // 正確:僅讀取
}

修飾函數(shù)返回值:限制返回值不可被修改(常見于返回指針/引用的場景,避免外部篡改內(nèi)部數(shù)據(jù))。

// 返回?cái)?shù)組首地址,禁止外部修改數(shù)組內(nèi)容
const int* getArr() {
    static int arr[3] = {1,2,3};
    return arr;
}
int main() {
    const int* p = getArr();
    *p = 4; // 錯(cuò)誤:返回值是 const,禁止修改
}

修飾類成員

const 成員變量:屬于對(duì)象的“常量”,必須在構(gòu)造函數(shù)初始化列表中初始化(不能在定義時(shí)直接賦值)。

class Person {
private:
    const int age; // const 成員變量
public:
    // 正確:在初始化列表中初始化
    Person(int a) : age(a) {}
    // 錯(cuò)誤:不能在構(gòu)造函數(shù)體內(nèi)賦值
    // Person(int a) { age = a; }
};

const 成員函數(shù):保證函數(shù)內(nèi)部不修改任何非 mutable 成員變量,函數(shù)聲明和定義都要加 const。

class Person {
private:
    int age;
public:
    // 聲明時(shí)加 const
    void showAge() const;      //語法:返回值類型 函數(shù)名() const;
};
// 定義時(shí)也要加 const(位置不能錯(cuò))
void Person::showAge() const {
    age = 20; // 錯(cuò)誤:const 函數(shù)禁止修改成員變量
    cout << age << endl; // 正確:僅讀取
}

修飾對(duì)象

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

  • 格式很簡單:在對(duì)象定義前加const,和定義const變量(比如 const int a=10)的邏輯一致。
#include <iostream>
#include <string>
using namespace std;

// 定義一個(gè)學(xué)生類
class Student {
public:
    string name;  // 成員變量:姓名
    int score;    // 成員變量:成績

    // 構(gòu)造函數(shù)(初始化姓名和成績)
    Student(string n, int s) : name(n), score(s) {}

    // 普通成員函數(shù):修改成績(可能改成員變量)
    void setScore(int s) {
        score = s;
    }

    // const 成員函數(shù):只打印信息(不修改成員變量)
    void showInfo() const {
        cout << "姓名:" << name << ",成績:" << score << endl;
    }
};
int main() {
    // 1. 普通對(duì)象(可以修改成員,調(diào)用任意函數(shù))
    Student s1("張三", 90); 
    s1.score = 85;          // 允許:普通對(duì)象能改成員變量
    s1.setScore(88);        // 允許:普通對(duì)象能調(diào)用非const函數(shù)
    s1.showInfo();          // 允許:普通對(duì)象也能調(diào)用const函數(shù)

    // 2. const對(duì)象(只讀,核心限制:不能改成員,只能調(diào)const函數(shù))
    const Student s2("李四", 85); 
    // s2.score = 90;       // 錯(cuò)誤!const對(duì)象不能直接修改成員變量
    // s2.setScore(92);     // 錯(cuò)誤!const對(duì)象不能調(diào)用非const函數(shù)
    s2.showInfo();          // 允許!const對(duì)象只能調(diào)用const成員函數(shù)

    return 0;
}

遵循兩個(gè)規(guī)則:

  • const對(duì)象的成員變量絕對(duì)不能修改。
  • const對(duì)象只能調(diào)用const成員函數(shù)。

static:“靜態(tài)存儲(chǔ)”與“作用域控制”

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

修飾全局變量

  • 作用:全局 static 變量的作用域僅限當(dāng)前 .cpp 文件,避免不同文件中“同名全局變量”的命名沖突。
  • 對(duì)比普通全局變量:普通全局變量默認(rèn)“跨文件可見”(用 extern 可引用),static 全局變量則“文件私有”。

示例:

// a.cpp
static int global_val = 5; // 僅 a.cpp 可見

// b.cpp
extern int global_val; // 錯(cuò)誤:無法引用 a.cpp 的 static 全局變量

修飾局部變量

  • 作用:局部 static 變量的“作用域”仍在函數(shù)內(nèi),但“存儲(chǔ)周期”是整個(gè)程序(僅初始化一次,函數(shù)調(diào)用結(jié)束后不銷毀)。
  • 典型場景:函數(shù)內(nèi)的計(jì)數(shù)器、全局唯一的臨時(shí)數(shù)據(jù)。

示例:

void countCall() {
    static int cnt = 0; // 僅初始化一次(第一次調(diào)用時(shí))
    cnt++;
    cout << "調(diào)用次數(shù):" << cnt << endl;
}
int main() {
    countCall(); // 輸出 1
    countCall(); // 輸出 2(cnt 未被銷毀)
}

修飾類成員

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

static 成員變量

  • 特點(diǎn):屬于整個(gè)類,所有對(duì)象共用同一內(nèi)存,必須在類外單獨(dú)初始化(不能在構(gòu)造函數(shù)中初始化)。由于static成員變量存儲(chǔ)在類的外部,計(jì)算類的大小時(shí)不包含在內(nèi)。

示例:統(tǒng)計(jì)類的對(duì)象創(chuàng)建個(gè)數(shù)

class Student {
private:
    static int total; // 聲明:屬于 Student 類
public:
    Student() { total++; } // 創(chuàng)建對(duì)象時(shí)計(jì)數(shù)+1
    ~Student() { total--; } // 銷毀對(duì)象時(shí)計(jì)數(shù)-1
    // 必須用 static 函數(shù)訪問 static 變量(見下文)
    static int getTotal() { return total; }
};

// 類外初始化:不加 static,需指定類名
int Student::total = 0;

int main() {
    Student s1, s2;
    cout << Student::getTotal(); // 輸出 2(兩個(gè)對(duì)象)
}

static成員函數(shù)

  • 特點(diǎn):沒有 this 指針(因?yàn)椴灰蕾噷?duì)象),只能訪問 static 成員變量/函數(shù),不能訪問非 static 成員。
  • 調(diào)用方式:直接用“類名::函數(shù)名”調(diào)用(無需創(chuàng)建對(duì)象)。
  • 示例:上文 Student::getTotal(),直接通過類名調(diào)用。

const 與 static 結(jié)合應(yīng)用

兩者結(jié)合的核心場景是“類的靜態(tài)常量”,即 static const(或 const static,兩者在類中等價(jià)),用于定義“類級(jí)別的常量”(所有對(duì)象共用,且不可修改),既實(shí)現(xiàn)了數(shù)據(jù)共享又達(dá)到了數(shù)據(jù)不可被改變的目的。

關(guān)鍵用法:類內(nèi)靜態(tài)常量的初始化

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

示例:

class Config {
public:
    // C++11+ 支持:類內(nèi)直接初始化靜態(tài)常量
    static const int MAX_NUM = 100;
    static const string DEFAULT_NAME; // 非字面量類型,需類外初始化
};

// 非字面量類型的 static const 成員,仍需類外初始化
const string Config::DEFAULT_NAME = "unknown";

注意:C++11 前,static const 成員變量必須在類外初始化,即使是字面量類型。

避坑指南

坑 1:const 變量能“強(qiáng)制修改”?

用指針強(qiáng)制轉(zhuǎn)換可以修改 const 變量,但這是“未定義行為”(編譯器不報(bào)錯(cuò),但運(yùn)行結(jié)果不可控,可能觸發(fā)崩潰),絕對(duì)禁止!

const int a = 5;
int* p = (int*)&a; // 強(qiáng)制轉(zhuǎn)換(危險(xiǎn)?。?
*p = 10; // 運(yùn)行時(shí)可能修改成功,但屬于未定義行為

坑 2:static 局部變量的線程安全?

  • C++11 及以后:static 局部變量的初始化是“線程安全”的(編譯器會(huì)加鎖,避免多線程同時(shí)初始化)。
  • C++11 前:非線程安全,多線程同時(shí)調(diào)用可能導(dǎo)致重復(fù)初始化。

坑 3:類 static 成員忘記類外初始化?

僅在類內(nèi)聲明 static 成員變量,未在類外初始化,會(huì)導(dǎo)致鏈接錯(cuò)誤(編譯器找不到變量的定義)。記住:static 類成員“聲明在類內(nèi),定義在類外”。

結(jié)尾總結(jié)

conststatic 雖基礎(chǔ),但用法靈活,核心記住兩點(diǎn):

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

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C語言內(nèi)存泄露很嚴(yán)重的解決方案

    C語言內(nèi)存泄露很嚴(yán)重的解決方案

    這篇文章主要介紹了C語言內(nèi)存泄露很嚴(yán)重的解決方案,預(yù)防內(nèi)存泄漏問題有多種方法,比如加強(qiáng)代碼檢視、工具檢測和內(nèi)存測試等,下面文章總結(jié)內(nèi)容需要的小伙伴可以參考一下
    2022-05-05
  • C語言非遞歸后序遍歷二叉樹

    C語言非遞歸后序遍歷二叉樹

    這篇文章主要為大家詳細(xì)介紹了C語言非遞歸后序遍歷二叉樹,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • 淺談分詞器Tokenizer

    淺談分詞器Tokenizer

    分詞器的工作就是分解文本流成詞(tokens).在這個(gè)文本中,每一個(gè)token都是這些字符的一個(gè)子序列。一個(gè)分析器(analyzer)必須知道它所配置的字段,但是tokenizer不需要,分詞器(tokenizer)從一個(gè)字符流(reader)讀取數(shù)據(jù),生成一個(gè)Token對(duì)象(TokenStream)的序列
    2021-06-06
  • C語言中單鏈表的基本操作指南(增刪改查)

    C語言中單鏈表的基本操作指南(增刪改查)

    鏈表跟數(shù)組不同的是非連續(xù)存儲(chǔ)結(jié)構(gòu),也就是說實(shí)現(xiàn)鏈表需要一個(gè)指針,每用完一個(gè)節(jié)點(diǎn)指針指向下一個(gè)節(jié)點(diǎn),直至表尾,下面這篇文章主要給大家介紹了關(guān)于C語言中單鏈表的基本操作之增刪改查的相關(guān)資料,需要的朋友可以參考下
    2021-09-09
  • 如何在C++中實(shí)現(xiàn)一個(gè)正確的時(shí)間循環(huán)器詳解

    如何在C++中實(shí)現(xiàn)一個(gè)正確的時(shí)間循環(huán)器詳解

    這篇文章主要給大家介紹了關(guān)于如何在C++中實(shí)現(xiàn)一個(gè)正確的時(shí)間循環(huán)器的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • C語言詳解判斷相同樹案例分析

    C語言詳解判斷相同樹案例分析

    這篇文章主要介紹了用C語言檢查兩棵樹是否相同,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2022-04-04
  • C/C++實(shí)現(xiàn)的游戲角色名稱名字隨機(jī)生成代碼

    C/C++實(shí)現(xiàn)的游戲角色名稱名字隨機(jī)生成代碼

    這篇文章主要介紹了C/C++實(shí)現(xiàn)的游戲角色名稱名字隨機(jī)生成代碼,本文特別針對(duì)一些古典游戲的角色名稱進(jìn)行隨機(jī)生成,需要的朋友可以參考下
    2015-05-05
  • C語言的各類變量和零值的比較詳解

    C語言的各類變量和零值的比較詳解

    這篇文章主要為大家介紹了C語言的各類變量和零值的比較,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • 一篇帶你了解C語言--位操作詳情

    一篇帶你了解C語言--位操作詳情

    這篇文章主要介紹了關(guān)于C語言位運(yùn)算的簡單示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • 一篇文章帶你用C語言玩轉(zhuǎn)結(jié)構(gòu)體

    一篇文章帶你用C語言玩轉(zhuǎn)結(jié)構(gòu)體

    本文主要介紹C語言 結(jié)構(gòu)體的知識(shí),學(xué)習(xí)C語言肯定需要學(xué)習(xí)結(jié)構(gòu)體,這里詳細(xì)說明了結(jié)構(gòu)體并附示例代碼,供大家參考學(xué)習(xí),有需要的小伙伴可以參考下
    2021-09-09

最新評(píng)論