抱歉:铁汁们,最近在做兼职,积累社会经验,多有拖欠,请多多包涵(抱拳)
引子:接上回我们讲了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+5
std::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,它们可以被视为原始指针的包装器,提供了自动内存管理。