3.16 含有可变参数的函数

3.16 含有可变参数的函数

用于编写函数参数不确定的函数,可以定义可变长度的形参表

3.16.1 含有可变参数的函数

C++标准中提供了两种主要的方法

  1. 如果所有的实参类型相同,可以传递一个名为initializer_list的标准库类型

    initializer_list

    initializer_list是一种标准库类型,用于表示某种特定类型的值的数组,该类型定义在同名的头文件中,也就是要include这个头文件(使用时需#include <initializer_list>

  2. 如果实参的类型不同,我们可以编写可变参数的模板

3.16.2 initializer_list提供的操作
initializer_list提供的操作 说明
initializer_list<T> lst; 默认初始化;T类型元素的空列表
initializer_list<T> lst{a, b, c...} lst的元素数量和初始值一样多;lst的元素是对应初始值的副本;列表中的元素是const
lst2(lst) lst2 = lst 拷贝或者赋值一个initializer_list对象但不拷贝列表中的元素;拷贝后原始列表和副本共享元素
lst.size() 列表中的元素数量
lst.begin() 返回指向lst首元素的指针
lst.end() 返回指向lst尾元素下一位置的指针
3.16.3 initializer_list的使用方法

initializer_list是一个类模板

使用模板时,我们需要在模板名字后面跟一对尖括号,括号内给出类型参数

C++ 复制代码
initializer_list<string> ls;//initializer_list的元素类型是string
initializer_list<int> li;//initializer_list的元素类型是int

initializer_list比较特殊的一点是,其对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值

简单来说:你可以读取initializer_list里的元素,但永远不能修改这些元素的值------哪怕你想在代码里直接赋值,编译器也会报错。下面用"通俗解释+代码示例"帮你彻底理解:

一、通俗理解

initializer_list想象成一个"只读的购物清单":

  • 你可以看清单上的每一项(读取元素);
  • 但你不能用笔把清单上的"苹果"改成"香蕉"(修改元素);
  • 若想改,只能重新写一份新清单(创建新的initializer_list),原清单永远不变。

二、代码示例:验证"无法修改元素"

下面的代码能直观体现这个特性,你可以复制到编译器中运行,看报错结果:

cpp 复制代码
#include <iostream>
#include <initializer_list>
using namespace std;

int main() {
    // 1. 创建一个initializer_list<int>,包含元素1、2、3
    initializer_list<int> lst = {1, 2, 3};

    // 2. 尝试修改第一个元素(编译器直接报错)
    // 错误写法:试图给常量元素赋值
    // lst.begin()[0] = 10;  // 这行代码会编译失败!

    // 3. 正确操作:只能读取元素,不能修改
    cout << "读取第一个元素:" << lst.begin()[0] << endl; // 输出1
    for (auto num : lst) {
        cout << num << " "; // 输出1 2 3(正常读取)
    }

    // 4. 若想"更新"元素,只能创建新的initializer_list
    initializer_list<int> new_lst = {10, 2, 3}; // 新清单,和原清单无关
    cout << "\n新列表第一个元素:" << new_lst.begin()[0] << endl; // 输出10
    return 0;
}

关键报错说明

如果你取消注释lst.begin()[0] = 10;这行,编译器会抛出类似错误:

复制代码
error: assignment of read-only location '* lst.std::initializer_list<int>::begin()'

翻译过来就是:"试图给只读的内存位置赋值"------本质是initializer_list的元素被编译器标记为const(常量),禁止写入操作。

三、为什么initializer_list要设计成"元素只读"?

这是C++标准的刻意设计,核心原因有2个:

  1. 简化底层实现initializer_list的拷贝/赋值不会复制元素(只是共享底层数组),如果允许修改元素,一个列表的修改会影响所有拷贝版本,引发不可控的bug;
  2. 语义匹配initializer_list的核心用途是"传递一组初始值"(比如给函数传可变参数),而非"存储可修改的数据集"------若需要可修改的集合,应该用vectorarray等容器。

四、和普通容器(如vector)的对比

用表格能更清晰看出差异:

操作 initializer_list vector(普通容器)
读取元素 ✅ 支持 ✅ 支持
修改元素(如v[0]=10 ❌ 禁止(编译报错) ✅ 支持
元素底层属性 const(常量) 普通变量(可读写)
核心用途 传递可变初始值 存储/修改数据集

总结

  1. initializer_list的元素是只读常量:只能读、不能改,修改会触发编译错误;
  2. 若需修改元素,不要用initializer_list,改用vectorarray等可读写容器;
  3. 这个设计是为了保证initializer_list的轻量性(拷贝共享元素)和语义安全性(避免意外修改)。

含有initializer_list形参的函数也可以同时拥有其他形参

3.16.4 initializer_list使用

在编写代码输出程序产生的错误信息时,最好统一用一个函数实现该功能,使得对所有错误的处理能够整齐划一,然而错误信息的种类不同,调用错误信息输出函数时传递的参数也会各不相同

使用initializer_list编写一个错误信息输出函数使其可以作用于可变参数的形参

相关推荐
郝学胜-神的一滴19 分钟前
Linux网络编程之listen函数:深入解析与应用实践
linux·服务器·开发语言·网络·c++·程序人生
有代理ip33 分钟前
成功请求的密码:HTTP 2 开头响应码深度解析
java·大数据·python·算法·php
YYuCChi36 分钟前
代码随想录算法训练营第三十四天 | 62.不同路径、63.不同路径||
算法
呱呱巨基39 分钟前
c语言 文件操作
c语言·开发语言·c++·笔记·学习
小明同学0139 分钟前
[C++进阶] 深度解析AVLTree
c++·算法·visualstudio
CoderCodingNo1 小时前
【GESP】C++五级练习题 luogu-P1031 [NOIP 2002 提高组] 均分纸牌
开发语言·c++·算法
云小逸2 小时前
【Nmap 设备类型识别技术】整体概况
服务器·c语言·网络·c++·nmap
梯度下降中2 小时前
求职面试中的线代知识总结
人工智能·线性代数·算法·机器学习
SmartBrain2 小时前
OCR 模型在医疗场景的选型研究
人工智能·算法·语言模型·架构·aigc·ocr
梵刹古音2 小时前
【C语言】 跳转语句
c语言·开发语言·算法