最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++之初始化列表詳解(initializer_list)

 更新時(shí)間:2025年09月18日 14:20:42   作者:MzKyle  
C++11引入std::initializer_list,用于封裝列表初始化的語法糖,實(shí)現(xiàn)容器、函數(shù)等場景的統(tǒng)一初始化方式,其本質(zhì)是輕量級(jí)只讀視圖,不存儲(chǔ)元素,僅通過指針和長度管理序列,支持容器構(gòu)造、參數(shù)傳遞等操作,但需注意生命周期與只讀限制

在 C++ 編程中,我們經(jīng)常會(huì)用到形如 vector<int> v = {1, 2, 3, 4}; 的語法——用花括號(hào)包裹一組元素直接初始化容器。

這種直觀且簡潔的寫法背后,依賴于 C++11 引入的一個(gè)特殊類型:std::initializer_list。

它不僅是列表初始化的“橋梁”,更是 C++ 標(biāo)準(zhǔn)庫設(shè)計(jì)中連接語法糖與底層實(shí)現(xiàn)的關(guān)鍵機(jī)制。

一、initializer_list的本質(zhì)

std::initializer_list<T> 是 C++11 新增的標(biāo)準(zhǔn)庫類型,定義于 <initializer_list> 頭文件中。

它的核心作用是:封裝一組同類型元素的初始化列表,為編譯器提供一種統(tǒng)一的方式處理花括號(hào) {} 包裹的元素序列。

簡單來說,當(dāng)你寫下 {a, b, c, d} 這樣的代碼時(shí),編譯器會(huì)自動(dòng)將這組元素轉(zhuǎn)換為一個(gè) initializer_list<T> 類型的臨時(shí)對(duì)象(其中 T 是元素的類型)。

這個(gè)臨時(shí)對(duì)象可以被傳遞給函數(shù)、作為構(gòu)造函數(shù)參數(shù),或用于賦值操作,從而實(shí)現(xiàn)“用一組值直接初始化對(duì)象”的目的。

二、initializer_list的底層結(jié)構(gòu):輕量級(jí)的“元素視圖”

initializer_list<T> 本身并不是一個(gè)容器(如 vectorarray),而是一個(gè)輕量級(jí)的“視圖”(view)——它不存儲(chǔ)元素本身,僅存儲(chǔ)指向元素序列的指針和序列長度。

其內(nèi)部結(jié)構(gòu)可簡化為:

template <class T>
class initializer_list {
public:
    using value_type = T;
    using reference = const T&;  // 注意:元素是只讀的
    using const_reference = const T&;
    using size_type = size_t;
    using iterator = const T*;   // 迭代器是 const 指針
    using const_iterator = const T*;

    // 構(gòu)造函數(shù)(由編譯器隱式調(diào)用,用戶無法直接構(gòu)造)
    constexpr initializer_list(const T* begin, const T* end) 
        : _M_array(begin), _M_size(end - begin) {}

    // 迭代器接口
    constexpr const T* begin() const noexcept { return _M_array; }
    constexpr const T* end() const noexcept { return _M_array + _M_size; }
    constexpr size_t size() const noexcept { return _M_size; }

private:
    const T* _M_array;  // 指向元素序列的首地址(編譯器分配)
    size_t _M_size;     // 元素個(gè)數(shù)
};

從結(jié)構(gòu)可見,initializer_list<T> 的核心特征是:

  1. 只讀性:元素指針 _M_arrayconst T*,迭代器也是 const T*,意味著無法通過 initializer_list 修改元素值(元素本身可能是可修改的,但列表視圖是只讀的)。
  2. 臨時(shí)性initializer_list 指向的元素序列由編譯器在棧上分配,生命周期與初始化列表的作用域一致(通常是臨時(shí)對(duì)象)。
  3. 輕量性:僅包含兩個(gè)成員(指針和長度),因此復(fù)制 initializer_list 時(shí)成本極低(僅復(fù)制指針和長度,不復(fù)制元素)。

三、initializer_list與vector<int>的“協(xié)作”

為什么 initializer_list<int> 能構(gòu)造 vector<int>?核心原因是 std::vector 專門設(shè)計(jì)了接受 initializer_list<T> 的構(gòu)造函數(shù),這是標(biāo)準(zhǔn)庫容器對(duì)列表初始化的“主動(dòng)適配”。

1. vector 的 initializer_list 構(gòu)造函數(shù)

std::vector<T> 的構(gòu)造函數(shù)中,有一個(gè)重載專門用于接收 initializer_list<T>

template <class T, class Allocator = std::allocator<T>>
class vector {
public:
    // 從 initializer_list 初始化
    vector(std::initializer_list<T> init, const Allocator& alloc = Allocator());
    // 其他構(gòu)造函數(shù)(如無參、指定大小、迭代器范圍等)
};

這個(gè)構(gòu)造函數(shù)的內(nèi)部實(shí)現(xiàn)邏輯大致是:

  1. 接收 initializer_list<T> 對(duì)象 init;
  2. 調(diào)用 init.begin()init.end() 獲取元素序列的起始和結(jié)束地址;
  3. 分配足夠的內(nèi)存(大小為 init.size());
  4. 遍歷 initializer_list 中的元素,將它們逐個(gè)復(fù)制到 vector 的內(nèi)存中。

例如,當(dāng)我們寫 vector<int> v = {1, 2, 3, 4}; 時(shí),編譯器會(huì)執(zhí)行以下步驟:

  • {1, 2, 3, 4} 轉(zhuǎn)換為 initializer_list<int> 臨時(shí)對(duì)象(假設(shè)為 init),其中 init.begin() 指向 1 的地址,init.size() 為 4;
  • 調(diào)用 vector<int>vector(initializer_list<int>) 構(gòu)造函數(shù),傳入 init;
  • 構(gòu)造函數(shù)根據(jù) init 的元素序列,在 vector 內(nèi)部初始化 4 個(gè)元素,最終得到包含 1,2,3,4 的向量。

2. 為什么直接傳四個(gè) int 不行?

當(dāng)我們嘗試用 emplace_back(nums[i], nums[j], nums[left], nums[right]) 構(gòu)造 vector<int> 時(shí),實(shí)際是向 vector 的構(gòu)造函數(shù)傳遞了四個(gè)獨(dú)立的 int 參數(shù)。但 vector<int> 并沒有接受“4 個(gè) int”的構(gòu)造函數(shù)——它的構(gòu)造函數(shù)要么接受長度和初始值(如 vector(4, 0)),要么接受迭代器范圍,要么接受 initializer_list<int>。因此,直接傳遞四個(gè) int 會(huì)導(dǎo)致“無匹配的構(gòu)造函數(shù)”錯(cuò)誤。

initializer_list<int> 恰好匹配了 vector 為列表初始化設(shè)計(jì)的構(gòu)造函數(shù),因此能夠正確初始化。

四、initializer_list的使用場景:不止于容器初始化

initializer_list 的作用遠(yuǎn)不止初始化容器,它是 C++ 中“列表初始化”語法的通用機(jī)制,適用于多種場景:

1. 容器初始化與賦值

這是最常見的場景。所有標(biāo)準(zhǔn)庫容器(vector、listmap、set 等)都提供了接受 initializer_list 的構(gòu)造函數(shù)和賦值運(yùn)算符:

#include <map>
#include <set>

// 初始化 vector
std::vector<int> v = {1, 2, 3};

// 初始化 map(鍵值對(duì)列表)
std::map<std::string, int> m = {{"a", 1}, {"b", 2}};

// 賦值操作
v = {4, 5, 6};  // 調(diào)用 vector::operator=(initializer_list<int>)

2. 函數(shù)參數(shù):接收變長同類型參數(shù)

initializer_list 可以作為函數(shù)參數(shù),接收任意數(shù)量的同類型元素(類似“變長參數(shù)列表”,但限制為同類型)。例如,實(shí)現(xiàn)一個(gè)計(jì)算多個(gè)整數(shù)之和的函數(shù):

#include <initializer_list>
#include <iostream>

int sum(std::initializer_list<int> nums) {
    int total = 0;
    for (int num : nums) {  // 可通過范圍 for 遍歷
        total += num;
    }
    return total;
}

int main() {
    std::cout << sum({1, 2, 3, 4}) << std::endl;  // 輸出 10
    return 0;
}

這里的 sum({1,2,3,4}) 中,{1,2,3,4} 被轉(zhuǎn)換為 initializer_list<int>,作為參數(shù)傳入函數(shù),函數(shù)通過迭代器遍歷所有元素。

3. 自定義類型的列表初始化

我們可以為自定義類添加接受 initializer_list 的構(gòu)造函數(shù),使其支持列表初始化:

#include <initializer_list>
#include <vector>

class MyArray {
private:
    std::vector<int> data;
public:
    // 支持列表初始化
    MyArray(std::initializer_list<int> init) : data(init) {}

    void print() {
        for (int num : data) {
            std::cout << num << " ";
        }
    }
};

int main() {
    MyArray arr = {10, 20, 30};  // 調(diào)用 MyArray(initializer_list<int>)
    arr.print();  // 輸出 "10 20 30"
    return 0;
}

通過這種方式,自定義類型可以像標(biāo)準(zhǔn)容器一樣使用直觀的列表初始化語法。

4. 返回值:函數(shù)返回一組同類型元素

函數(shù)也可以返回 initializer_list<T>,方便返回一組臨時(shí)元素:

#include <initializer_list>

std::initializer_list<int> get_numbers() {
    return {1, 2, 3};  // 返回初始化列表
}

int main() {
    for (int num : get_numbers()) {
        std::cout << num << " ";  // 輸出 "1 2 3"
    }
    return 0;
}

注意:返回的 initializer_list 指向的元素是臨時(shí)的,因此不能存儲(chǔ)其副本并在后續(xù)使用(生命周期已結(jié)束)。

五、列表初始化的優(yōu)先級(jí):為什么{}會(huì)優(yōu)先匹配initializer_list?

當(dāng)一個(gè)類同時(shí)有多個(gè)構(gòu)造函數(shù)時(shí),編譯器在處理 {} 初始化時(shí)會(huì)有明確的優(yōu)先級(jí):如果存在接受 initializer_list 的構(gòu)造函數(shù),{} 初始化會(huì)優(yōu)先匹配該構(gòu)造函數(shù),而非其他重載。

例如:

#include <initializer_list>
#include <iostream>

class MyClass {
public:
    // 接受 initializer_list 的構(gòu)造函數(shù)
    MyClass(std::initializer_list<int> list) {
        std::cout << "Initializer_list constructor: " << list.size() << " elements\n";
    }

    // 接受兩個(gè) int 的構(gòu)造函數(shù)
    MyClass(int a, int b) {
        std::cout << "Two int constructor: " << a << ", " << b << "\n";
    }
};

int main() {
    MyClass obj1(1, 2);  // 調(diào)用 MyClass(int, int)
    MyClass obj2{1, 2};  // 優(yōu)先調(diào)用 MyClass(initializer_list<int>)
    return 0;
}

輸出結(jié)果:

Two int constructor: 1, 2
Initializer_list constructor: 2 elements

這一規(guī)則確保了 {} 語法與列表初始化的語義一致,避免了歧義。如果確實(shí)需要調(diào)用非 initializer_list 構(gòu)造函數(shù),可以使用圓括號(hào) () 而非花括號(hào) {}。

六、initializer_list的限制與注意事項(xiàng)

盡管 initializer_list 方便易用,但它的設(shè)計(jì)也有明確的限制,使用時(shí)需特別注意:

1. 元素必須是同類型

initializer_list<T> 要求所有元素的類型必須相同(或可隱式轉(zhuǎn)換為 T)。

例如,{1, 2.0, 3}2.0double,若 Tint,則 2.0 會(huì)被隱式轉(zhuǎn)換為 2;若無法轉(zhuǎn)換(如 {1, "hello"}),則編譯報(bào)錯(cuò)。

2. 元素是只讀的

initializer_list<T> 的迭代器是 const T*,因此無法通過 initializer_list 修改元素值:

#include <initializer_list>

void modify(std::initializer_list<int> list) {
    // 錯(cuò)誤:不能修改元素(迭代器是 const)
    // *list.begin() = 100;  // 編譯報(bào)錯(cuò):assignment of read-only location
}

如果需要修改元素,需先將 initializer_list 中的元素復(fù)制到可修改的容器(如 vector)中。

3. 生命周期與臨時(shí)對(duì)象

initializer_list 指向的元素序列由編譯器在棧上分配,是臨時(shí)對(duì)象,其生命周期與初始化列表的作用域一致。因此,不能存儲(chǔ) initializer_list 的副本并在其生命周期外使用

#include <initializer_list>
#include <vector>

// 錯(cuò)誤示例:返回的 initializer_list 指向已銷毀的元素
std::initializer_list<int> get_list() {
    return {1, 2, 3};  // 元素在函數(shù)返回后銷毀
}

int main() {
    auto list = get_list();
    // 未定義行為:list 指向的元素已被釋放
    // for (int num : list) { ... }
    return 0;
}

4. 不能直接構(gòu)造 initializer_list

initializer_list 沒有公有的構(gòu)造函數(shù),用戶無法手動(dòng)創(chuàng)建其實(shí)例,只能通過 {} 語法由編譯器自動(dòng)生成:

// 錯(cuò)誤:無法直接構(gòu)造 initializer_list
std::initializer_list<int> list(1, 2, 3);  // 編譯報(bào)錯(cuò)

七、initializer_list的設(shè)計(jì)意義

initializer_list 看似簡單,卻是 C++ 語言進(jìn)化中“語法糖”與“底層邏輯”結(jié)合的典范。它的核心價(jià)值在于:

  1. 統(tǒng)一初始化語法:讓數(shù)組、容器、自定義類型都能通過 {} 實(shí)現(xiàn)直觀的初始化,減少記憶負(fù)擔(dān)。
  2. 簡化容器使用:無需手動(dòng)調(diào)用 push_back 或指定大小,直接通過元素列表初始化容器。
  3. 支持變長同類型參數(shù):為函數(shù)提供了一種簡潔的方式接收任意數(shù)量的同類型元素,比 C 風(fēng)格的變長參數(shù)(va_list)更安全、更易用。

總結(jié)

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

相關(guān)文章

  • c語言實(shí)現(xiàn)詞頻統(tǒng)計(jì)的簡單實(shí)例

    c語言實(shí)現(xiàn)詞頻統(tǒng)計(jì)的簡單實(shí)例

    下面小編就為大家?guī)硪黄猚語言實(shí)現(xiàn)詞頻統(tǒng)計(jì)的簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-09-09
  • C++中引用的使用總結(jié)

    C++中引用的使用總結(jié)

    以下是對(duì)C++中引用的使用進(jìn)行了詳細(xì)的總結(jié)介紹,需要的朋友可以過來參考下,希望對(duì)大家有所幫助
    2013-10-10
  • C語言實(shí)現(xiàn)經(jīng)典24點(diǎn)算法

    C語言實(shí)現(xiàn)經(jīng)典24點(diǎn)算法

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)經(jīng)典24點(diǎn)算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • C++之set自定義排序問題

    C++之set自定義排序問題

    這篇文章主要介紹了C++之set自定義排序問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • C++中sprintf()函數(shù)的使用詳解

    C++中sprintf()函數(shù)的使用詳解

    本篇文章是對(duì)C++中sprintf()函數(shù)的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • Qt教程之QSqlQueryModel的使用詳解

    Qt教程之QSqlQueryModel的使用詳解

    QSqlQueryModel是QSqlTableModel的父類,它封裝了執(zhí)行SELECT語句從數(shù)據(jù)庫查詢數(shù)據(jù)的功能,本文將為大家介紹一下QSqlQueryModel的使用,需要的可以參考一下
    2022-11-11
  • OpenCV實(shí)戰(zhàn)之基于Hu矩實(shí)現(xiàn)輪廓匹配

    OpenCV實(shí)戰(zhàn)之基于Hu矩實(shí)現(xiàn)輪廓匹配

    這篇文章主要介紹了利用C++ OpenCV實(shí)現(xiàn)基于Hu矩的輪廓匹配,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)OpenCV有一定的幫助,感興趣的可以學(xué)習(xí)一下
    2022-01-01
  • 基于C語言實(shí)現(xiàn)井字棋游戲

    基于C語言實(shí)現(xiàn)井字棋游戲

    這篇文章主要為大家詳細(xì)介紹了基于C語言實(shí)現(xiàn)井字棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 淺談使用Rapidxml 庫遇到的問題和分析過程(分享)

    淺談使用Rapidxml 庫遇到的問題和分析過程(分享)

    下面小編就為大家?guī)硪黄獪\談使用Rapidxml 庫遇到的問題和分析過程(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • C語言實(shí)現(xiàn)圖片放大縮小

    C語言實(shí)現(xiàn)圖片放大縮小

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)圖片放大縮小,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05

最新評(píng)論

饶河县| 望奎县| 常宁市| 克拉玛依市| 开封县| 怀仁县| 庆云县| 青河县| 武义县| 岳西县| 辽中县| 凤阳县| 城市| 内黄县| 罗平县| 乌兰察布市| 玛纳斯县| 浠水县| 民权县| 新龙县| 桦甸市| 浮梁县| 佛学| 马关县| 林周县| 永丰县| 庄浪县| 彭泽县| 安仁县| 元氏县| 钟山县| 舞钢市| 雷山县| 化德县| 甘洛县| 彩票| 德令哈市| 绥江县| 秦安县| 即墨市| 巫山县|