【C++】C++11

目录

1. 初始化列表

2. 右值引用

3. 拷贝禁用

4. lambda表达式

5. 可变参数模板

6. 包装器


1. 初始化列表

#include <iostream>
#include <list>
#include <vector>
using namespace std;

int main()
{
	auto i = { 1, 2, 3 };
	cout << typeid(i).name() << endl;		// class std::initializer_list<int>

	int a = 10;
	int b{ 10 };		// 一切变量皆可用 {} 赋值,默认变量不建议这样用
	cout << a << "," << b << endl;

	vector<int> arr1 = { 1, 2, 3, 4, 5 };
	vector<int> arr2{ 1, 2, 3, 4, 5 };		// vector、list都可以用初始化列表赋值
	for (auto e : arr1)
	{
		cout << e << ' ';
	}
	cout << endl;
	for (auto e : arr2)
	{
		cout << e << ' ';
	}
	cout << endl;

	struct Point
	{
		int _x, _y, _z;
	};

	list<Point> ls1 = { {1, 2, 3}, {3, 3, 3}, {3, 6, 9} };
	for (auto& e : ls1)
	{
		cout << e._x << ", " << e._y << ", " << e._z << endl;
	}
	cout << endl;
}

2. 右值引用

左值引用与右值引用:

#include <iostream>
#include <list>
#include <vector>
using namespace std;

int main()
{
	int num = 10;
	int& a = num;			// 左值引用
	const int& a0 = 10;		// 常量左值引用可以操作右值
	cout << "a0: " << a0 << endl;

	int&& a1 = 10;
	cout << "a1: " << a1 << endl;
	a1 = 100;
	cout << "a1:" << a1 << endl;

	const int&& a2 = 1000;
	cout << "a2: " << a2 << endl;
	// 常量右值引用,在实际应用场景中很少出现
	// 一方面,右值引用主要用于移动语义和完美转发,前者需要有修改右值的权限
	// 另一方面,常量右值引用的作用就是引用一个不可修改的右值,这项工作完全可以由常量左值引用实现

	return 0;
}

转移语义:构造时有拷贝构造和移动构造两种策略,转移构造通过转移语义就是将原变量赋给新变量,而不做拷贝,这样原变量销毁,但是原变量的数据没有销毁,提高了效率。当编译器识别到构造函数的参数是纯右值或者将亡值时,会采用移动构造策略。

完美转发:std::forward() 函数将保持变量类型的属性

#include <iostream>
#include <list>
#include <vector>
using namespace std;

vector<int> test()
{
	vector<int> tmp = { 1, 2, 3, 4 };
	return tmp;
}

void reference(string& str)
{
	cout << "左值" << endl;
}

void reference(string&& str)
{
	cout << "右值" << endl;
}

// 完美转发
template<typename T>
void perfect_forward(T&& t)
{
	// 完美茶转发,保持他的属性
	reference(t);
	//reference(std::forward<T>(t));
}

int main()
{
	vector<int> v = test();
	for (auto& e : v)
	{
		cout << e << ' ';
	}
	cout << endl << endl;
	// test 函数的返回值是一个将亡值:即将被销毁,却能够被移动的值。
	// 要拿到一个将亡值,就需要用到右值引用:T&&,通过移动构造,减少拷贝次数

	string lv1 = "test_str";	// 这是一个左值
	string&& rv1 = move(lv1);	// std::move 可以将左值转移为右值

	reference(lv1);				// 左值
	cout << "lv1: " << lv1 << endl;
	perfect_forward(lv1);		// 左值

	reference(rv1);				// 左值
	cout << "rv1: " << rv1 << endl;
	perfect_forward(rv1);		// 左值
	// rv1 虽然引用了一个右值,但由于它是一个引用,所以它是一个左值

	reference("str");			// 右值
	perfect_forward("str");		// 右值

	return 0;
}

移动构造、移动赋值:当类没有实现移动构造,且没有实现析构函数、拷贝构造、拷贝赋值重载中的任意一个,编译器才会默认生成一个移动构造。

3. 拷贝禁用

delete 关键字不止用于空间的释放,还用于类的拷贝禁用

#include <iostream>
using namespace std;

template<class T>
class Test
{
public:
	Test()
	{}

	Test(const Test& t) = delete;
	// 防止从内部和外部进行拷贝构造,应用于单例模式和智能指针

	void func()
	{
		Test<T> tmp(*this);
	}

private:
	T p[10];
};

int main()
{
	Test<int> t1;

	//Test<int> t2(t1);
	//t1.func();		
	// 从内部和外部拷贝都会报错:尝试引用已删除的函数


	return 0;
}

4. lambda表达式

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

#include <iostream>
using namespace std;

int main()
{
	// 用lambda表达式比较int数据
	auto compare = [](int x, int y) {return x > y; };
	//auto compare = [](int x, int y) -> bool{return x > y; };
	// [capture-lest]: 捕捉列表,在lambda函数开始处,编译器根据 [] 判断接下来代码是否为lambda函数函数
	// (parameters): 参数列表,如无参数可省略
	// -> returntype: 返回值类型,可省略,由编译器进行返回值类型推导
	// {statement}: 函数体
	
	// lambda 本质是一个可调用的对象,相比于仿函数写法更简洁可读性更高

	cout << compare(10, 20) << endl;

	auto add = [](int x, int y) {return x + y; };
	cout << add(10, 20) << endl;

	int a = 100;
	auto sub =  [a](int x) { return a - x; };
	cout << sub(50) << endl;

	int b = 1000;
	//auto swap1 = [&a, &b]()mutable	// 传值捕捉,生成临时变量
	auto swap1 = [&a, &b]()mutable		// 传引用捕捉
	{
		int tmp = a;
		a = b;
		b = tmp;
	};
	// 捕捉列表捕捉的数据带const属性
	// 加上 mutable 之后捕捉列表的数据就可以改变了
	swap1();
	cout << "a=" << a << ", b=" << b << endl;	// a=1000, b=100


	//auto swap2 = [=]()mutable			// 传值捕捉所有变量
	auto swap2 = [&]()mutable			// 传引用捕捉所有变量
	{
		int tmp = a;
		a = b;
		b = tmp;
	};
	// 捕捉列表捕捉的数据带const属性
	// 加上 mutable 之后捕捉列表的数据就可以改变了
	swap2();
	cout << "a=" << a << ", b=" << b << endl;	// a=100, b=1000

	int x = 200;
	auto swap3 = [=, &a, &b]()mutable			// 混合捕捉
	{
		a = x;
		b = x;
		x = a + b;
	};
	// 捕捉列表捕捉的数据带const属性
	// 加上 mutable 之后捕捉列表的数据就可以改变了
	swap3();
	cout << "a=" << a << ", b=" << b << ", x=" << x << endl;	// a=200, b=200, x=200

	return 0;
}
#include <iostream>
#include <thread>
#include <vector>
#include <Windows.h>
using namespace std;

int main()
{
	vector<thread> vThread;
	vThread.resize(5);

	int i = 0;
	int x = 0;
	for (auto& t : vThread)
	{
		t = thread([&i, x]()
			{
				while (i < 20)
				{
					cout << "thread-" << x << " -> " << i << endl;
					Sleep(1000);
					++i;
				}
			});
		++x;
	}

	for (auto& t : vThread)
	{
		t.join();
	}

	return 0;
}

5. 可变参数模板

#include <iostream>
using namespace std;

void ShowList()
{
	cout << endl;
}

// Args 是一个模板参数包
template<class T, class ...Args>
void ShowList(T val, Args... args)
{
	// 解析参数包
	cout << val << " ";
	ShowList(args...);
}

int main()
{
	ShowList(1);
	ShowList(1, 1.0);
	ShowList(1, 1.0, string("hello"));
	ShowList();

	return 0;
}

6. 包装器

#include <iostream>
#include <functional>
using namespace std;

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

struct Func
{
	int operator()(int a, int b)
	{
		return a + b;
	}
};

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

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

int main()
{
	function<int(int, int)> f1;
	f1 = func;
	cout << f1(1, 1) << endl;

	function<int(int, int)> f2(func);
	cout << f2(2, 2) << endl;

	function<int(int, int)> f3 = Func();
	cout << f3(3, 3) << endl;

	function<int(int, int)> f4 = [](int a, int b) {return a + b; };
	cout << f4(4, 4) << endl;

	function<int(int, int)> f5 = Plus::plusi;			// 类静态成员函数指针
	cout << f5(5, 5) << endl;

	function<int(Plus, int, int)> f6 = &Plus::plusd;	// 类成员函数指针
	cout << f6(Plus(), 6, 6) << endl;

	Plus plus;
	function<int(Plus, int, int)> f7 = &Plus::plusd;
	cout << f7(plus, 7, 7) << endl;

	function<int(int, int)> f8 = [&plus](int a, int b)->int {return plus.plusd(a, b); };
	cout << f8(8, 8) << endl;

	return 0;
}

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AllinTome

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值