可变参数函数,initializer_list,省略号形参

一、可变参数函数

1.这种能够接收非固定个数参数的函数就是可变参数函数

2.initializer_list 标准库类型,该类型能够使用的前提条件是:所有的实参类型相同。

二、initializer_list (初始化列表)

1.如果一个函数,它的实参 数量不可预知,但是所有的参数的类型相同,我们就可以用这个,

initializer_list类型的形参来接收。

2.initializer_list 是C++11提供的新类型,是一个类模板。

3.begin(),end(),size() 等方法。

#include <iostream>
#include <future>
#include <vector>
#include <map>
#include <functional>
#include <string>
#include <algorithm>
#include <ctime>
#include <initializer_list>

using namespace std;

void printvalue(initializer_list<string> tmpstr)
{
	/*for (auto beg = tmpstr.begin(); beg != tmpstr.end(); beg++)
	{
		cout << (*beg).c_str() << endl;
	}
	*/

	for (auto& tmp : tmpstr)  
	{
		cout << tmp.c_str() << endl;
	}

	cout << "size : " << tmpstr.size() << endl;
}

int main()
{
	initializer_list<int> myarray; //数组,元素类型是int,空列表(空数组)
	initializer_list<int> myarray2 = {12,14,16,20,30};
	//注意initializer_list 中的元素值,永远是常量值,不能够被改变。

	initializer_list<string> myarray3 = { "C","C++","Assembly","Python","Shell","JAVA"};

	printvalue(myarray3);

	cout << endl;

	printvalue({"C","C++","Python","Shell"});

	return 0;
}

2.2 拷贝和赋值

 1.拷贝、赋值一个initializer_list对象,不会拷贝列表中的元素。原来对象和拷贝或者赋值出来的对象共享表中的元素。

#include <iostream>
#include <future>
#include <vector>
#include <map>
#include <functional>
#include <string>
#include <algorithm>
#include <ctime>
#include <initializer_list>

using namespace std;


int main()
{
	initializer_list<string> myarray = { "C","C++","Assembly","Python","Shell","JAVA"};
	initializer_list<string> myarray2(myarray);

	initializer_list<string> myarray3;
	myarray3 = myarray2;

	return 0;
}

2.3 初始化列表做构造函数参数

#include <iostream>
#include <future>
#include <vector>
#include <map>
#include <functional>
#include <string>
#include <algorithm>
#include <ctime>
#include <initializer_list>

using namespace std;

class CT
{
public:
	explicit CT(const initializer_list<int>& tmpvalue)
	{

	}
};

int main()
{
	//CT ct1 = {10,20,30,40,50}; //隐式类型转换,构造函数前面用 explict 就不能用这种隐式类型转换了。

	CT ct1{10,20,30,40,50};
	CT ct2 = CT({10,20,30,40,50});

	return 0;
}

三、省略号形参(...)

1.省略号形参一般无法正确处理类类型对象;也属于可变参数函数。

2.这种省略形参的可变参数函数,虽然参数数量不固定,但是函数的所有参数是存储在线性的连续的stack空间。

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

注意:

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

2. ...形参只能出现在形参列表的最后一个位置。void myfunc(形参列表,...)

3. ... 之前的,可以省略

4.如果有多个普通参数,那么va_start(valist,msg) ,第二个参数必须绑定 ... 之前的那个参数。例如:

void funcTest(const int num,const char* msg...)

此时必须绑定msg参数,而不是num。

5.一般这些可变参数类型是数值型或者是字符串类型还能够正常处理,其他类类型都不能正常处理,所以用的场合并不多。

#include <iostream>
#include <future>
#include <vector>
#include <map>
#include <functional>
#include <string>
#include <algorithm>
#include <ctime>
#include <initializer_list>
#include <stdarg.h>

using namespace std;

double sum(int num, ...)
{
	va_list valist; //创建一个 va_list类型的变量

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

	for (int i = 0; i < num; i++)
	{
		sum = sum + va_arg(valist,int);//参数2说明返回的类型为int
	}
	va_end(valist); //释放va_list

	return sum;
}
//void funcTest(const char* msg, ...) ,可以省略
void funcTest(const char* msg...)
{
	va_list valist; //创建一个 va_list类型的变量
	int csgs = atoi(msg); //拿到可变参数数量
	va_start(valist, msg); //使valist指向起始的参数
	int paramcount = 0;
	while (paramcount < csgs)
	{
		char* p = NULL;
		p =  va_arg(valist, char*);//参数2说明返回的类型为int
		printf("第%d参数是:%s\n",paramcount,p);
		paramcount++;
	}
	va_end(valist); //释放va_list
}

int main()
{
	cout << sum(3,100,200,300) << endl;

	cout << sum(2, 100, 200, 300) << endl; //参数给多了,300会被自动忽略。
	cout << sum(2, 100, 200) << endl;

	cout << endl;

	funcTest("3","C","C++","Python");


	return 0;
}

posted @ 2022-12-03 18:53  repinkply  阅读(161)  评论(0)    收藏  举报