• 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)
    {}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    //展开函数的终止
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

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

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

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

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

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

    捕捉列表

    #include
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

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

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

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

    包装器

    为什么要有包装器?

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在这里插入图片描述

    类模板

    template <class T> function; // undefined
    
    template <class Ret, class... Args>
    class function<Ret(Args...)>;
    
    • 1
    • 2
    • 3
    • 4
    • Ret:表示调用函数的返回类型;
    • Args:表示函数的参数列表的参数;

    简单对上面例题使用

    #include
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    类成员函数

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在这里插入图片描述

    bind

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

    bind函数的语法如下:

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

    其中,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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在这里插入图片描述

  • 相关阅读:
    boost算法
    工作≤4 年,小公司反复横跳,技术热情不足被当成纯资源、成长缓慢的人
    分布式服务框架总是要学的,大佬的笔记就赠于你吧
    Java之HashMap系列--创建并初始化成员的方法
    结构化技能——特征筛选
    以太网链路聚合与交换机堆叠,集群
    【若依(ruoyi)】bootstrapTable 有选中行按钮可用,无选中行按钮不可用/单选和多选按钮样式
    SD系列——图像高清化算法方法
    java spring cloud 企业工程管理系统源码+二次开发+定制化服务
    【React的特性&事件&表单的使用&函数组件】
  • 原文地址:https://blog.csdn.net/m0_74068921/article/details/137358042