C++入门小馆:C++11第三弹(可变参数模板)
嘿,各位技术潮人!好久不见甚是想念。生活就像一场奇妙冒险,而编程就是那把超酷的万能钥匙。此刻,阳光洒在键盘上,灵感在指尖跳跃,让我们抛开一切束缚,给平淡日子加点料,注入满满的
passion。准备好和我一起冲进代码的奇幻宇宙了吗?Let’s go!
我的博客:yuanManGan
我的专栏:C++入门小馆 C言雅韵集 数据结构漫游记 闲言碎语小记坊 进阶数据结构 走进Linux的世界 题山采玉 领略算法真谛
C++ 11
4. 可变参数模板
4.1 基本语法及原理
什么是可变参数呢?
我们的printf
函数就是一个可变参数函数,我们可以向prinf
函数传入任意数量的参数,并且参数的类型可以不一样。这就是可变参数!
C++11
中支持可变参数模板,也就是支持可变参数的函数模板和类模板,可变数目的参数被称为参数包,存在两种参数包:模板参数包,表示零或多个模板参数;函数参数包:表示零或多个函数参数。
下面是可变参数模板的格式:
template <class ...Args> void Fuc(Args... args){}
template <class ...Args> void Fuc(Args&... args){}
template <class ...Args> void Fuc(Args&&... args){}
sizeof...
用来计算参数包的个数。(编译时计算)
4.2 包扩展
我们可以使用参数包来写可变参数模板,但这不是我们常用的方法。
void ShowList()
{cout << endl;
}
template<class T,class...Args>
void ShowList(T x, Args&& ...args)
{cout << x << " ";ShowList(args...);
}template<class ...Args>
void print(Args&& ...args)
{ShowList(args...);//cout << sizeof...(args) << endl;//sizeof...编译时计算
}
本质是利用了递归。
int main()
{double a = 1.1;print();print(2);print(2,string("ssss"));print(2,string("ssss"), a);return 0;
}
也可以这样写
template <class T>
int GetArg(const T& x)
{cout << x << " ";return 0;
}template <class ...Args>
void Arguments(Args... args)
{}template <class ...Args>
void Print(Args... args)
{// 注意GetArg必须返回或者到的对象,这样才能组成参数包给Arguments// GetArg的返回值组成实参参数包,传给ArgumentsArguments(GetArg(args)...);cout << endl;
}
这两种方法了解一下就行了。
4.3 `empalce系列接口
在STL
中所有的函数都有一个emplace
版本
它们都说emplace版本效率更高,那让我们来看看效率高在哪里呢
int main()
{std::list<bit::string> lt;//传左值bit::string s1("ssssssss");lt.push_back(s1);lt.emplace_back(s1);cout << "********************************************" << endl;//传右值、lt.push_back(move(s1));lt.emplace_back(move(s1));cout << "********************************************" << endl;return 0;
}
我们发现传右值和左值它们的效率是一样的。
我们如果直接传参,就发现emplace
版本只进行了一次构造就能完成,这是为什么呢?
我们的push_back
在创建类对象时就确定了T为string
类型,而emplace_back
是直接推演的,推演为const char*
这个对象就可以直接构造string
类型。
我们再试试插入的是pair
的对象。
int main()
{std::list<pair<bit::string, int>> lt3;// 传左值效率用法都是一样的pair<bit::string, int> kv1("xxxxxx", 1);lt3.push_back(kv1);lt3.emplace_back(kv1);cout << "*****************************************" << endl;// 传右值效率用法都是一样的pair<bit::string, int> kv2("xxxxxx", 1);lt3.push_back(move(kv2));pair<bit::string, int> kv3("xxxxxx", 1);lt3.emplace_back(move(kv3));cout << "*****************************************" << endl;// emplace_back的效率略高一筹lt3.push_back({ "11111111111111", 1 });//lt3.emplace_back({ "11111111111111", 1 }); //不支持lt3.emplace_back("11111111111111", 1);cout << "*****************************************" << endl;return 0;
}