C++類(lèi)和對(duì)象之初始化列表的使用方式
C++初始化列表詳解:性能優(yōu)化與正確實(shí)踐
在C++編程中,初始化列表是構(gòu)造函數(shù)的重要組成部分,它不僅能提升代碼性能,還能確保成員變量被正確初始化。本文將深入探討初始化列表的語(yǔ)法、應(yīng)用場(chǎng)景及最佳實(shí)踐。
什么是初始化列表?
初始化列表是構(gòu)造函數(shù)的一部分,用于在對(duì)象創(chuàng)建時(shí)直接初始化成員變量。
它位于構(gòu)造函數(shù)參數(shù)列表之后,函數(shù)體之前,使用冒號(hào)(:)和逗號(hào)(,)分隔各成員的初始化操作。
class MyClass {
private:
int value;
std::string name;
const double pi;
int& ref;
public:
// 使用初始化列表的構(gòu)造函數(shù)
MyClass(int val, const std::string& nm, int& r)
: value(val), name(nm), pi(3.14159), ref(r) {
// 構(gòu)造函數(shù)體
}
};初始化列表的三大核心作用
1. 性能優(yōu)化:避免不必要的賦值操作
對(duì)于非基本類(lèi)型(如std::string、std::vector),初始化列表可以直接調(diào)用其構(gòu)造函數(shù),而不是先默認(rèn)構(gòu)造再賦值。
對(duì)比示例:
// 使用初始化列表(高效)
class A {
public:
A(const std::string& str) : data(str) {} // 直接構(gòu)造
private:
std::string data;
};
// 使用賦值(低效)
class B {
public:
B(const std::string& str) { data = str; } // 默認(rèn)構(gòu)造 + 賦值
private:
std::string data;
};2. 強(qiáng)制初始化:處理const和引用成員
const成員和引用必須在初始化時(shí)賦值,初始化列表是唯一的方式。
class Config {
private:
const int maxSize; // 常量成員
std::string& filePath; // 引用成員
public:
Config(int size, std::string& path)
: maxSize(size), filePath(path) {} // 必須在初始化列表中賦值
};3. 基類(lèi)初始化:正確調(diào)用父類(lèi)構(gòu)造函數(shù)
當(dāng)基類(lèi)沒(méi)有默認(rèn)構(gòu)造函數(shù)時(shí),必須通過(guò)初始化列表顯式調(diào)用其帶參構(gòu)造函數(shù)。
class Base {
public:
Base(int value) { /* ... */ }
};
class Derived : public Base {
public:
Derived(int x) : Base(x) { /* ... */ } // 調(diào)用基類(lèi)構(gòu)造函數(shù)
};4.必須使用初始化列表的情況
在C++中,引用、const成員變量以及沒(méi)有默認(rèn)構(gòu)造函數(shù)的類(lèi)類(lèi)型成員變量必須在構(gòu)造函數(shù)初始化列表中進(jìn)行初始化,這是由它們的語(yǔ)義和C++對(duì)象生命周期的規(guī)則決定的。
1. 引用(Reference)
引用的本質(zhì)是對(duì)象的別名,一旦綁定到某個(gè)對(duì)象就無(wú)法重新綁定。因此:
- 必須在創(chuàng)建時(shí)初始化:引用沒(méi)有“未初始化”狀態(tài),必須在定義時(shí)指定其引用的對(duì)象。
- 構(gòu)造函數(shù)體執(zhí)行前成員已初始化:構(gòu)造函數(shù)體中的代碼執(zhí)行時(shí),成員變量已經(jīng)完成初始化。若在構(gòu)造函數(shù)體內(nèi)對(duì)引用賦值,實(shí)際上是對(duì)已初始化的引用進(jìn)行賦值操作(改變被引用對(duì)象的值),而非初始化引用本身。
示例:
class Example {
private:
int& ref; // 引用必須初始化
public:
Example(int& value) : ref(value) {} // 正確:初始化列表中初始化
};2. const 成員變量
const成員變量的值在對(duì)象的生命周期內(nèi)不可修改,因此:
- 必須在初始化時(shí)賦值:
const變量一旦初始化就不能再被賦值。 - 初始化列表是唯一機(jī)會(huì):構(gòu)造函數(shù)體執(zhí)行前,
const成員必須已經(jīng)被賦予初始值。
示例:
class Example {
private:
const int value; // const成員必須初始化
public:
Example(int val) : value(val) {} // 正確:初始化列表中初始化
};3. 沒(méi)有默認(rèn)構(gòu)造函數(shù)的類(lèi)類(lèi)型成員
如果一個(gè)類(lèi)沒(méi)有默認(rèn)構(gòu)造函數(shù)(即沒(méi)有無(wú)參構(gòu)造函數(shù)),則在創(chuàng)建該類(lèi)的對(duì)象時(shí)必須顯式提供參數(shù)。因此:
- 必須通過(guò)參數(shù)初始化:編譯器無(wú)法默認(rèn)構(gòu)造該成員,必須顯式調(diào)用其帶參構(gòu)造函數(shù)。
- 初始化列表提供了顯式調(diào)用的機(jī)會(huì):在初始化列表中,可以指定參數(shù)來(lái)調(diào)用成員的帶參構(gòu)造函數(shù)。
示例:
class Inner {
public:
Inner(int x) {} // 只有帶參構(gòu)造函數(shù)
};
class Example {
private:
Inner inner; // Inner沒(méi)有默認(rèn)構(gòu)造函數(shù)
public:
Example(int x) : inner(x) {} // 正確:顯式調(diào)用Inner的帶參構(gòu)造函數(shù)
};為什么不能在構(gòu)造函數(shù)體中初始化?
構(gòu)造函數(shù)體中的代碼執(zhí)行時(shí),成員變量已經(jīng)完成初始化(默認(rèn)初始化或編譯器生成的初始化)。因此:
- 引用和
const成員:無(wú)法在構(gòu)造函數(shù)體中重新初始化,因?yàn)樗鼈儽仨氃诔跏蓟瘯r(shí)就確定值。 - 無(wú)默認(rèn)構(gòu)造函數(shù)的類(lèi)成員:如果未在初始化列表中顯式構(gòu)造,編譯器會(huì)嘗試調(diào)用其默認(rèn)構(gòu)造函數(shù),但由于該類(lèi)沒(méi)有默認(rèn)構(gòu)造函數(shù),會(huì)導(dǎo)致編譯錯(cuò)誤。
初始化列表的作用是在對(duì)象的內(nèi)存分配后、構(gòu)造函數(shù)體執(zhí)行前,顯式控制成員變量的初始化過(guò)程。對(duì)于引用、const成員和無(wú)默認(rèn)構(gòu)造函數(shù)的類(lèi)成員,初始化列表是唯一能滿(mǎn)足其初始化語(yǔ)義的地方。若不使用初始化列表,代碼將因“未初始化的引用/const成員”或“無(wú)法默認(rèn)構(gòu)造的類(lèi)成員”而編譯失敗。
初始化列表的語(yǔ)法規(guī)則
1. 初始化順序由聲明順序決定
成員變量的初始化順序由其在類(lèi)中聲明的順序決定,而非初始化列表中的順序。錯(cuò)誤的順序可能導(dǎo)致未定義行為。
class Example {
private:
int a;
int b;
public:
// 危險(xiǎn):初始化列表順序與聲明順序不一致
Example(int value) : b(value), a(b) {} // a先被初始化,但此時(shí)b未初始化
};2. 支持表達(dá)式初始化
可以使用常量、函數(shù)返回值或其他成員變量進(jìn)行初始化。
class Point {
private:
int x;
int y;
int distance;
public:
Point(int _x, int _y)
: x(_x), y(_y),
distance(calculateDistance(_x, _y)) {} // 使用函數(shù)返回值初始化
int calculateDistance(int x, int y) const {
return std::sqrt(x*x + y*y);
}
};初始化列表 vs 構(gòu)造函數(shù)體賦值
| 特性 | 初始化列表 | 構(gòu)造函數(shù)體賦值 |
|---|---|---|
| 執(zhí)行時(shí)機(jī) | 對(duì)象創(chuàng)建時(shí) | 對(duì)象創(chuàng)建后 |
| 性能 | 通常更高效 | 可能涉及額外的賦值操作 |
| const/引用成員 | 支持 | 不支持 |
| 基類(lèi)初始化 | 必須使用 | 不可用 |
總結(jié)
初始化列表總結(jié):
- 無(wú)論是否顯?寫(xiě)初始化列表,每個(gè)構(gòu)造函數(shù)都有初始化列表;
- 無(wú)論是否在初始化列表顯?初始化成員變量,每個(gè)成員變量都要?初始化列表初始化;

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Opencv?視頻讀取與寫(xiě)入的實(shí)現(xiàn)示例
本文將介紹如何使用OpenCV進(jìn)行視頻讀寫(xiě)。通過(guò)閱讀本文,您將了解如何讀取視頻文件、處理視頻幀、寫(xiě)入視頻文件等操作,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08
C語(yǔ)言循環(huán)結(jié)構(gòu)與時(shí)間函數(shù)用法實(shí)例教程
這篇文章主要介紹了C語(yǔ)言循環(huán)結(jié)構(gòu)與時(shí)間函數(shù)用法,是C語(yǔ)言中非常重要的一個(gè)技巧,需要的朋友可以參考下2014-08-08
C++中l(wèi)ist的使用方法及常用list操作總結(jié)
這篇文章主要介紹了C++中l(wèi)ist的使用方法及常用list操作總結(jié)的相關(guān)資料,需要的朋友可以參考下2017-06-06
C++中BitSet和Bloom_Filter的實(shí)現(xiàn)
本文主要介紹了C++中BitSet和Bloom_Filter的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02
C++定時(shí)器實(shí)現(xiàn)和時(shí)間輪介紹
這篇文章主要介紹了C++定時(shí)器實(shí)現(xiàn)和時(shí)間輪介紹,定時(shí)器可以由很多種數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn),比如最小堆、紅黑樹(shù)、跳表、甚至數(shù)組都可以,其本質(zhì)都是拿到最小時(shí)間的任務(wù),然后取出該任務(wù)并執(zhí)行,更多相關(guān)內(nèi)容介紹,需要的小伙伴可以參考一下2022-09-09
Qt利用QState狀態(tài)機(jī)實(shí)現(xiàn)控件互斥操作詳解
這篇文章主要為大家詳細(xì)介紹了Qt如何利用QState狀態(tài)機(jī)實(shí)現(xiàn)控件互斥操作,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-12-12

