C++进阶--C++11(2)

C++11第一篇

C++11是C++编程语言的一个版本,于2011年发布。C++11引入了许多新特性,为C++语言提供了更强大和更现代化的编程能力。

可变参数模板

在C++11中,可变参数模板可以定义接受任意数量和类型参数的函数模板或类模板。它可以表示0到任意个数,任意类型的参数。通过使用(…)来声明可变参数,省略号后面的参数被称为参数包。

下面是可变参数的函数模板:

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... 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...);
}

int main()
{
	Showlist(1);
	Showlist(1, 'A');
	Showlist(1, 'A', std::string("sort"));
	return 0;
}

在这里插入图片描述

emplace_back()

在这里插入图片描述

测试与push_back()的区别:

int main()
{
	std::list<fnc::string> lt1;

	fnc::string s1("xxxx");
	lt1.push_back(s1);
	lt1.push_back(move(s1));
	cout << "=============================================" << endl;

	fnc::string s2("xxxx");
	lt1.emplace_back(s2);
	lt1.emplace_back(move(s2));
	cout << "=============================================" << endl;

	lt1.push_back("xxxx");
	lt1.emplace_back("xxxx");
	cout << "=============================================" << endl;

	std::list<pair<fnc::string, fnc::string>> lt2;
	pair<fnc::string, fnc::string> kv1("xxxx", "yyyy");
	lt2.push_back(kv1);
	lt2.push_back(move(kv1));
	cout << "=============================================" << endl;

	pair<fnc::string, fnc::string> kv2("xxxx", "yyyy");
	lt2.emplace_back(kv2);
	lt2.emplace_back(move(kv2));
	cout << "=============================================" << endl;

	lt2.emplace_back("xxxx", "yyyy");
	cout << "=============================================" << endl;


	return 0;
}

在这里插入图片描述
再测试:

class Date
{
public:
	Date(int year=1900, int month=1, int day=1)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date(int year, int month, int day)" << endl;
	}
	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._day)
	{
		cout << "Date(const Date& d)" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	//直接在参数中插入
	std::list<Date> lt1;
	lt1.push_back({ 2024,3,30 });
	lt1.emplace_back(2024, 3, 30);

	//直接插入已有的对象
	cout << endl;
	Date d1(2023, 1, 1);
	lt1.push_back(d1);
	lt1.emplace_back(d1);

	//插入匿名对象
	cout << endl;
	lt1.push_back(Date(2023, 1, 1));
	lt1.emplace_back(Date(2023, 1, 1));


	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

lambda

在这里插入图片描述

lambda语法表达式

[capture-list] (parameters) mutable -> return-type { statement}

  • [capture-list]:捕捉列表:位于lambda表达式最前位置,编译器通过[]来进行判断,能捕捉上下文中的变量给lambda表达式使用;
  • (parameters):参数列表,与函数的参数列表使用一致,如果没有参数的话,可省略使用;
  • mutable:默认情况下,lambda函数是一个const函数,使用mutable可以取消const性。使用该单词,不可省略参数列表。
  • -> return-type :返回值类型,用于声明函数的返回值类型,没有返回值进行省略;一般有返回值也可以省略,通过编译器进行推导。
  • {statement}:函数主体,除了使用参数列表的参数,也可使用捕捉列表的参数。

接下来看lambda的简单使用:

int main()
{
	//auto add = [](int a, int b)->int{return a + b; };
	auto add = [](int a, int b) {return a + b; };
	cout << add(1, 21) << endl;

	auto swap = [](int& a, int& b)
	{
		int tmp = a;
		a = b;
		b = tmp;
	};
	int x = 2, y = 22;
	swap(x, y);
	cout << x << " " << y << endl;

	auto func = []() {cout << "lambda" << endl; };
	func();

	return 0;
}

在这里插入图片描述

对上面sort的改装:
在这里插入图片描述

捕捉列表

#include<algorithm>
int main()
{
	int x = 1, y = 2;
	auto swap = [&x, &y]()mutable
	{
		int tmp = x;
		x = y;
		y = tmp;
	};
	swap();
	cout << x << " " << y << endl;

	int m = 3, n = 4;
	//传值捕捉'=':捕捉当前域的所有对象
	auto func1 = [=]()
	{
		return m * n - x - y;
	};
	cout << func1() << endl;

	//传引用捕捉:捕捉当前域所有对象
	auto func2 = [&]()
	{
		x++;
		y++;
		return m * n - x - y;
	};
	cout << func2() << endl;

	//x:2,y:3,m:3,n:4
	//对n传值捕捉,其他的传引用捕捉
	auto func3 = [&, n]()
	{
		x++;
		y++;
		m++;
		//n++;错误
		return m * n - x - y;
	};
	cout << func3() << endl;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

lambda底层

class Rate
{
public:
	Rate(double rate) : _rate(rate)
	{}

	double operator()(double money, int year)
	{
		return money * _rate * year;
	}
private:
	double _rate;
};

int main()
{
	//函数对象/仿函数
	double rate = 0.49;
	Rate r1(rate);
	r1(10000, 2);

	// lambda
	auto r2 = [=](double monty, int year)->double {return monty * rate * year;};
	r2(10000, 2);

	auto f1 = [] {cout << "hello world" << endl; };
	auto f2 = [] {cout << "hello world" << endl; };

	f1();
	f2();

	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

包装器

为什么要有包装器?

template<class F, class T>
T useF(F f, T x)
{
	static int count = 0;
	cout << "count:" << ++count << endl;
	cout << "count:" << &count << endl;

	return f(x);
}

double f(double i)
{
	return i / 2;
}

struct Functor
{
	double operator()(double d)
	{
		return d / 3;
	}
};

int main()
{
	// 函数名
	cout << useF(f, 11.11) << endl;

	// 函数对象
	cout << useF(Functor(), 11.11) << endl;

	// lamber表达式
	cout << useF([](double d)->double { return d / 4; }, 11.11) << endl;

	return 0;
}

在这里插入图片描述

类模板:

template <class T> function; // undefined

template <class Ret, class... Args>
class function<Ret(Args...)>;
  • Ret:表示调用函数的返回类型;
  • Args:表示函数的参数列表的参数;

简单对上面例题使用

#include<functional>

int main()
{
	// 函数指针
	function<double(double)> fc1 = f;
	fc1(11.11);
	cout << useF(fc1, 11.11) << endl;

	// 函数对象
	function<double(double)> fc2 = Functor();
	fc2(11.11);
	cout << useF(fc2, 11.11) << endl;

	// lambda表达式
	function<double(double)> fc3 = [](double d)->double { return d / 4; };
	fc3(11.11);
	cout << useF(fc3, 11.11) << endl;

	return 0;
}

在这里插入图片描述

类成员函数

int f(int a, int b)
{
	return a + b;
}

class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}

	double plusd(double a, double b)
	{
		return a + b;
	}
};

int main()
{
	// 普通函数
	function<int(int, int)> fc1 = f;
	cout << fc1(1, 1) << endl;

	// 静态成员函数
	function<int(int, int)> fc2 = &Plus::plusi;
	cout << fc2(1, 1) << endl;

	// 非静态成员函数
	// 非静态成员函数需要对象的指针或者对象去进行调用
	function<double(Plus, double, double)> fc3 = &Plus::plusd;
	cout << fc3(Plus(), 1, 1) << endl;

	return 0;
}

在这里插入图片描述

bind

在C++中,bind是一个函数模板,位于<functional>头文件中,用于创建函数对象(也称为函数绑定器),可以将参数绑定到函数调用中。

bind函数的语法如下:

template< class Fn, class... Args >
bind( Fn&& fn, Args&&... args );

其中,Fn表示要绑定的函数或可调用对象,Args表示要绑定的参数。

使用bind函数可以实现函数的延迟调用、固定部分参数等功能。

简单使用

int Sub(int a, int b)
{
	return a - b;
}

class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}

	double plusd(double a, double b)
	{
		return a - b;
	}
};

int main()
{
	// 调整参数顺序
	int x = 10, y = 20;
	cout << Sub(x, y) << endl;

	auto f1 = bind(Sub, placeholders::_2, placeholders::_1);
	cout << f1(x, y) << endl;

	function<double(Plus, double, double)> fc3 = &Plus::plusd;
	cout << fc3(Plus(), 1, 1) << endl;

	// 调整参数的个数
	// 某些参数绑死
	function<double(double, double)> fc4 = bind(&Plus::plusd, Plus(), placeholders::_1, placeholders::_2);
	cout << fc4(2, 3) << endl;

	function<double(double)> fc5 = bind(&Plus::plusd, Plus(), placeholders::_1, 20);
	cout << fc5(2) << endl;

	return 0;
}

在这里插入图片描述

相关推荐

  1. C++】12.模板

    2024-04-07 05:42:02       5 阅读
  2. C++--C++11包装器

    2024-04-07 05:42:02       27 阅读
  3. C++:模板

    2024-04-07 05:42:02       29 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-07 05:42:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-07 05:42:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-07 05:42:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-07 05:42:02       18 阅读

热门阅读

  1. 在使用clickhouse的一些心得

    2024-04-07 05:42:02       21 阅读
  2. RobotFramework测试框架(6)测试用例文件结构

    2024-04-07 05:42:02       29 阅读
  3. 面对对象编程(四)

    2024-04-07 05:42:02       17 阅读
  4. leetcode 169.多数元素

    2024-04-07 05:42:02       45 阅读
  5. ROC与决策树介绍

    2024-04-07 05:42:02       22 阅读
  6. 在 HTML 中禁用 Chrome 浏览器的 Google 翻译功能

    2024-04-07 05:42:02       36 阅读
  7. MongoDB的简单使用

    2024-04-07 05:42:02       20 阅读
  8. leetcode 72.编辑距离

    2024-04-07 05:42:02       22 阅读
  9. 深入了解go的通道类型

    2024-04-07 05:42:02       16 阅读
  10. 外刊杂志经济学人获取方式

    2024-04-07 05:42:02       18 阅读
  11. golang mutex

    2024-04-07 05:42:02       18 阅读
  12. 【Rust】基础语法

    2024-04-07 05:42:02       20 阅读
  13. 设计模式:外观模式

    2024-04-07 05:42:02       17 阅读
  14. 机器学习软件perming的使用文档

    2024-04-07 05:42:02       14 阅读