116 C++ 可变参数函数,initializer_list (初始化列表), 省略号形参

一 可变参数函数

有时候我们传递的参数是不固定的。

这种能接受非固定个数参数的函数就是可变参数函数

怎么实现呢?就要用到 initializer_list 标准库类型

该类型能够使用的前提条件是:所有的实参类型相同。

二,initializer_list(初始化列表) C++11的类模版

如果一个函数,它的实参数量不可预知,但是所有参数的类型相同,我们就可以使用这个initializer_list 类型的形参来接收

我们把 initializer_list 理解成某种类型值的数组。

这个类模版里面指定的类型模版参数就是数组里保存的数据的类型

需要包含 #include <initializer_list> 头文件 或者 iostream

要注意的是 initializer_list<int >myarray 中的元素永远都是常量值。不能被改变。

1. 基本方法 :begin(), end()遍历,size()获取元素个数

void func150(initializer_list<int> myarray) {
	//遍历形参,类似于迭代器的遍历
	for (auto iter = myarray.begin(); iter != myarray.end();++iter) {
		cout << "  " << * iter ;
	}
	cout << endl;
	cout << "myarray.size = " << myarray.size() << endl;
}
void func151(initializer_list<string> myarraystr) {
	//遍历形参,类似于迭代器的遍历
	for (auto iter = myarraystr.begin(); iter != myarraystr.end(); ++iter) {
		cout << "  " << (*iter).c_str();
	}
	cout << endl;
	cout << "myarraystr.size = " << myarraystr.size() << endl;
}

void main() {
	initializer_list<int> myarray;//就看成一个数组了,元素类型是int。
	initializer_list<int> myarray2 = { 12,16,18,80,90 };//一共5个元素
	//要注意的是 myarray 或者myarray2中的元素永远都是常量值。
	func150(myarray2);

	func151({"nihao","china"});
	cout << "duandian" << endl;

	//12  16  18  80  90
	//	myarray.size = 5
	//	nihao  china
	//	myarraystr.size = 2
	//	duandian
}

上述代码中值的说一下的地方:

C++11使用大括号里面放值,做为一种比较通用的初始化方式,可用于很多的类型。

begin() 和 end()方法类似于 迭代器的

2. initializer_list 拷贝和赋值 不会额外生成一份,是共享的

initializer_list 是个类模版,具体case就是一个类对象,那么这个类对象肯定也是可以拷贝和赋值的

copy 和 赋值 都不会 重新copy一份,而是原来的 mystr 和 mystr1共享一份,mystr 和 mystr2共享一份

	// copy 和 赋值 都不会 重新copy一份,而是原来的 mystr 和 mystr1共享一份,mystr 和 mystr2共享一份
	initializer_list<string> mystr = {"nihao","china","zhenxing"};
	initializer_list<string> mystr1(mystr);
	initializer_list<string> mystr2;
	mystr2 = mystr;
	 
	//debug发现  mystr mystr1 mystr2 中里面的string内容的地址都是一致的
	//	mystr[原始视图] = { _First = 0x008ffdac "nihao" _Last = 0x008ffe00 < 字符串中的字符无效。 > }
	//	mystr1[原始视图] = { _First = 0x008ffdac "nihao" _Last = 0x008ffe00 < 字符串中的字符无效。 > }
	//	mystr2[原始视图] = { _First = 0x008ffdac "nihao" _Last = 0x008ffe00 < 字符串中的字符无效。 > }
	cout << "duandian" << endl;

3.initializer_list 初始化列表做构造函数参数

class Teacher158 {
public:
	explicit Teacher158(const initializer_list<int> &temvalue) {

		cout << "duandian1" << endl;
	}
	Teacher158(string str) {

	}
	
};

void main() {
	cout << "111" << endl;
	Teacher158 tea(); //是一个函数声明,它声明了一个名为 tea 的函数,返回类型为 Teacher158
	cout << "222" << endl;
	Teacher158 tea1({1,2,3});
	Teacher158 tea3{ 100000,2000000,3000000 };
	//Teacher158 tea2 = { 4,5,66666666 };//隐式类型转换,还是会调用构造函数。
	//如果我们想禁止 隐式类型转换,需要在构造方法前面加上 explicit
}

三 省略号形参(...) 省略号形参一般无法正确处理类类型对象,在C++要少用,最好不要用,这里写出来是为了知识点的完整。

省略号形参(...) 也是可以变参数函数。能正确的处理int ,char *;

虽然这种参数数量不固定,但是函数的所有参数是存储在线性的连续的栈空间的。

而且这种可变参数函数必须至少有一个普通参数,我们就可以通过这个普通参数来寻址后续的所有可变参数的类型以及值。

需要包含头文件 #include <stdarg.h>

#include <stdarg.h>


//需要用到 stdarg.h中的几个宏
double func159(int num, ...) {//一般num里面传递进来的是可变参数的数量。
	va_list valist;//创建一个 va_list类型的变量,按f12 看va_list 实际上是 char*

	//该函数的目的是计算传递进来的 可变参数的和
	double sum = 0;

	va_start(valist, num);//使valist指向起始的参数

	for (int i = 0; i < num; ++i) {
		sum = sum + va_arg(valist, int);//va_arg是个宏,va_arg宏的第二个参数表明 func159函数除第一个参数外,都是int
		//该宏用于变参数函数调用过程中,type是当前参数类型,调用该宏后,ap指向变参数列表中的下一个参数,返回ap指向的参数值,是一个类型为type的表达式。
	}

	va_end(valist);//释放valist
	return sum;
}

void main() {
	cout << func159(5, 100, 200, 300, 400, 500) << endl;
}

注意说明:

  1. 至少有一个有效的形参,形参不能全部是...

2.三个.只能出现在形参列表的最后一个位置

3,三个.之前的,是可以省略的

4,如果有多个普通参数,那么va_start(valist, num)中的num,必须是...紧前面的那个

5,一般只能处理 数值型 或者char * 型,遇到类类型不能正常处理

6.在C++中不建议使用,能看懂就行

相关推荐
Rverdoser6 分钟前
RabbitMQ的基本概念和入门
开发语言·后端·ruby
dj24429457079 分钟前
JAVA中的Lamda表达式
java·开发语言
工业3D_大熊23 分钟前
3D可视化引擎HOOPS Luminate场景图详解:形状的创建、销毁与管理
java·c++·3d·docker·c#·制造·数据可视化
暮色_年华37 分钟前
Modern Effective C++ Item 11:优先考虑使用deleted函数而非使用未定义的私有声明
c++
流星白龙40 分钟前
【C++习题】10.反转字符串中的单词 lll
开发语言·c++
尘浮生1 小时前
Java项目实战II基于微信小程序的校运会管理系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
MessiGo1 小时前
Python 爬虫 (1)基础 | 基础操作
开发语言·python
Tech Synapse1 小时前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
乌啼霜满天2491 小时前
JDBC编程---Java
java·开发语言·sql
Smile丶凉轩1 小时前
微服务即时通讯系统的实现(服务端)----(1)
c++·git·微服务·github