学习STL源码遇到的C++新知识(三)可变参数

写在前面

在array类源码看到这样一段代码

template<class _First,
	class... _Rest>
	array(_First, _Rest...)
		-> array<typename _Enforce_same<_First, _Rest...>::type, 1 + sizeof...(_Rest)>;

于是决定深入了解一下c++变长参数的用法。

 

变长参数

可变参数是c++11的新特性,它允许函数的输入参数为不确定个,通常用“ ... ”代替。

void fun(int start, ...)

像上述代码这样,就声明了一个可变参数的函数。它以start为首,放入不确定个数的int类型的参数。

先来看一个代码

#include <iostream>
#include<stdarg.h>
using namespace std;

void fun(int start, ...) {
	va_list args;
	va_start(args, start);

	int arg = start;
	while (arg != -1) {
		cout << arg << " ";
		arg = va_arg(args, int);
	}
	
	va_end(args);
}

int main()
{
	fun(1, 2, 3, 4, 5, 6, 7, 8, 9, -1);
	return 0;
}

解释:

在main函数中的fun函数的-1参数是截止标志(可变参数不知道会有几个参数被传入,所以要手动设置结束方式,一般第一个参数为参数个数,或者最后一个参数为结尾标志,本次使用后者)

观察fun函数我们发现,访问可变参数使用了以下变量和方法(这些都在stdarg.h这个头文件中):

  1. va_list

  2. void va_start( va_list arg_ptr, prev_param ); 

  3. type va_arg( va_list arg_ptr, type ); 

  4. void va_end( va_list arg_ptr ); 

va_list是声明了一个可变参数的列表,它使用va_start()进行初始化,并指定首个数值,va_arg()是访问下一个参数,类似于链表的next,最后使用va_end()释放内存等杂七杂八的东西;

变长参数的实现

va_list

首先打开va_list的源码,它的定义如下:

typedef char* va_list;

 

可以看出va_list是一个char型指针。

va_start()

打开va_start(),我们发现他是重名了 __crt_va_start

#define va_start __crt_va_start

 继续追踪,发现以下代码

__crt_va_start(ap, x) 
((void)(__vcrt_assert_va_start_is_not_reference<decltype(x)>(), __crt_va_start_a(ap, x)))

__vcrt_assert_va_start_is_not_reference<decltype(x)>()的意思估计是如果start不是一个引用就断言,实现如下:

extern "C++"
    {
        template <
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值