本文主要是介绍可变参数模板与包装器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
抱歉:铁汁们,最近在做兼职,积累社会经验,多有拖欠,请多多包涵(抱拳)
引子:接上回我们讲了C++11的几种新增,今天就来接着讲C++11中比较有用的二个东西可变参数模板与包装器。
可变参数模板:当我们进行cout来打印时或cin来进行输入时,我们发现我们打印使用任意数量好任意数量类型的东西,你是否会思考为什么呢?其实都是可变参数模板的功劳,那何为可变参数模板呢?
概念:
可变参数模板是C++11引入的一个特性,它允许模板函数或类接受任意数量的模板参数。这种特性极大地增强了模板的灵活性,使得我们可以编写能够接受不确定数量参数的泛型代码。在标准库中,std::cout
和 std::cin
就是使用了可变参数模板技术的典型例子
可变参数模板的基本语法:
template<typename... Args>
ReturnType functionName(Args&&... args) {
// 使用args包中的参数
}
这里的 Args...
是一个模板参数包(template parameter pack),而 args...
是一个函数参数包,它们允许函数或类模板接受任意数量的参数。
如何显示参数包里面的参数呢?
一,利用递归
//递归终止函数
template <class T>
void ShowList(const T& t)
{cout << t << endl;
}
// 展开函数
template <class T, class ...Args>
void ShowList(T value, Args... args)
{cout << value << " ";ShowList(args...);
}
二,利用逗号表达式
template <class T>
void PrintArg(T t)
{cout << t << " ";
}
//展开函数
template <class ...Args>
void ShowList(Args... args)
{int arr[] = { (PrintArg(args), 0)... };cout << endl;
}
STL容器中的empalce相关接口函数(利用了可变参数模板):
区别:直接构造》》》
但是我们会发现其实差别也不到,as:emplace_back是直接构造了,push_back // 是先构造,再移动构造,其实也还好
实例代码:
#include <vector>
#include <string>
#include <map>int main() {// 使用emplace_back在vector中构造一个字符串std::vector<std::string> strings;strings.emplace_back("Hello, World!");// 使用emplace在map中构造一个键值对std::map<int, std::string> scores;int studentId = 1;scores.emplace(std::piecewise_construct,std::forward_as_tuple(studentId),std::forward_as_tuple("A"));return 0;
}
可变参数的引用:
一,实现print()任意打印!(其实也可以用输出流来打印自定义类型数据)
#include <iostream>// 可变参数模板函数,用于打印任意数量和类型的参数
template<typename... Args>
void print(Args... args) {((std::cout << args << ", "), ...); // 使用C++17的折叠表达式std::cout << "\n"; // 换行
}int main() {print(1, "Hello", 3.14, 'a'); // 打印整数、字符串、浮点数和字符
}
二,你可以使用可变参数模板来实现递归模板函数,例如计算参数包中所有整数的和:
template<typename T>
T sum(T value) {return value;
}template<typename T, typename... Args>
T sum(T first, Args... rest) {return first + sum(rest...);
}int main() {auto total = sum(1, 2, 3, 4, 5); // 计算1+2+3+4+5std::cout << "Total: " << total << std::endl; // 输出15
}
包装器
在C++中,"包装器"可能指的是多种不同的概念,但通常它指的是一种设计模式或技术,用于提供一个接口或包装,以改变或增强现有对象或类型的功能。在C++11中,包装器可能与智能指针、lambda表达式或函数包装有关
function
在C++中,function
是标准库中的一个模板类,位于 <functional>
头文件中。std::function
是一个通用的多态函数包装器,它可以存储、调用和复制任何可调用对象,例如普通函数、Lambda表达式、函数对象以及成员函数指针。
std::function
的主要用途是提供一个可调用的接口,该接口可以与任何类型的可调用实体一起工作,而不需要关心其具体的类型。这使得 std::function
成为实现回调机制、事件处理等模式的理想选择。
注意点:
1,function使用为<返回类型(引用类型,引用类型)>
2,function来包装普通成员函数时要用&,返回要传this*所以我们参数要加一个类*来进行通过
测试代码as:
double e(const int&a,const int&b)
{return (a + b) / 2;
}class b
{
public:double e(const int& a, const int& b){return (a + b) / 3;}
};int main()
{auto vt3 = bind(e, 100, placeholders::_1);cout << vt3(2) << endl;function<double(int, int)> vt = &e;cout << vt(3,3) << endl;function<double(b, int, int)> vt1 = &b::e;function<double(b*, int, int)> vt2 = &b::e;cout << vt1(b(), 3, 3) << endl;b h;cout << vt2(&h, 3, 3) << endl;function<double(int)> vt4 = bind(&b::e, b(),placeholders::_1,100);cout << vt4(2) << endl;return 0;
}
bind:
std::bind
是 C++ 标准库中的一个函数模板,位于 <functional>
头文件中。它用于创建一个新的可调用对象(通常是一个函数对象),这个新对象将一个或多个参数绑定到一个可调用实体(如函数、Lambda 表达式、成员函数等)的参数上。std::bind
返回一个 std::function
对象,它可以在之后被调用。
底层:
注意点:
1,使用时,可以用来绑定调用顺序,或者进行绑定参数
2,调用bind的一般形式:auto newCallable = bind(callable,arg_list); 其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的 callable的参数。当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中 的参数。 arg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是“占位符”,表示 newCallable的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对 象中参数的位置:_1为newCallable的第一个参数,_2为第二个参数,以此类推
测试代码:
double e(const int&a,const int&b)
{return (a + b) / 2;
}class b
{
public:double e(const int& a, const int& b){return (a + b) / 3;}
};int main()
{auto vt3 = bind(e, 100, placeholders::_1);cout << vt3(2) << endl;function<double(int, int)> vt = &e;cout << vt(3,3) << endl;function<double(b, int, int)> vt1 = &b::e;function<double(b*, int, int)> vt2 = &b::e;cout << vt1(b(), 3, 3) << endl;b h;cout << vt2(&h, 3, 3) << endl;function<double(int)> vt4 = bind(&b::e, b(),placeholders::_1,100);cout << vt4(2) << endl;return 0;
}
智能指针包装器:
C++11引入了新的智能指针类型,如std::unique_ptr、std::shared_ptr和std::weak_ptr,它们可以被视为原始指针的包装器,提供了自动内存管理。
有趣的连接:(可拿来做题)
感谢大家支持,下次要讲什么?我先来个图,大家猜猜(偷笑)
这篇关于可变参数模板与包装器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!