C++11的几点特性


前言

       C++11相比于 C++98/03有了极大的变化 ,其中包含了约140 个新特性。C ++11页对 C++03 标准中 600 个多个缺陷进行了修正, C++11相较于以前的版本 能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅 功能更强大,而且能提升程序员的开发效率

一、列表的初始化

1.C++11扩大了{}初始化列表的使用范围,不仅可以对数组进行初始化,也可以用于所有的内置类型和用户自定义类型(使用初始化列表时=可加可不加)。

#include<iostream>
#include<vector>
using namespace std;
template<class Type>
class Array
{
public:
	Array() :ar(nullptr), capacity(0), size(0)
	{}
	Array(int sz)
	{
		capacity = sz;
		ar = new Type[capacity];
		size = 0;
	}
	//多个对象想要支持列表初始化,需给该类(模板类)添加一个带有initializer_list类型参数的构造函数。
	//注意:initializer_list是系统自定义的类模板,该类模板中主要有三个方法:begin()、end()迭代器,获取中间元素个数的方法size()。
	Array(initializer_list<Type> lt) :size(0)
	{
		capacity = lt.size();
		ar = new Type[capacity];
		auto it = lt.begin();
		while (it != lt.end())
		{
			ar[size++] = *it++;
		}
	}
private:
	Type* ar;
	size_t capacity;
	size_t size;
};

int main()
{
	//内置类型变量
	int a{ 0 };
	int a1 = { 0 };
	//数组
	int array1[] = { 1,2,3,4 };
	int array2[]{ 1,2,3,4 };
	int array3[2]{ 1,2 };
	//动态数组
	int* array4 = new int[4]{ 1,2,3,4 };
	//容器
	vector<int> v{ 1,2,3,4 };
	//自定义类型
	Array<int> A1{ 3 };
	Array<int> A2 = { 1,2,3,4,5 };
	return 0;
}
​

二、变量类型推导

1.在不清楚变量类型或者类型过于复杂时可以使用auto进行类型推导

using namespace std;
int main()
{
	int a = 0;
	auto b = a;
	cout << typeid(b).name() << endl;

	vector<int> v{ 1,2,3,4 };
	auto it = v.begin();
	cout << typeid(it).name() << endl;
}

 

三、默认成员函数控制

        C++11对于空类编译器会默认生成的函数:构造函数、析构函数、拷贝构造函数、赋值运算符重载函数、&和const&的重载、移动构造、移动拷贝构造等函数。

1.显示缺省函数:如果自己定义了某函数又想让编译器生成该函数的默认版本,在默认函数定于或声明时加上=default。

2.删除默认函数:如果要禁止编译器生成某一函数的默认函数,可以在该函数的声明后面加上=delete。

class ex
{
public:
	ex(int n):_m(n)
	{}
	//显示缺省函数,让编译器生成默认构造函数
	ex() = default;
	//禁止编译器生成默认的拷贝构造函数
	ex(const ex&) = delete;
private:
	int _m;
};

四、左值与右值

1.左值与右值的主要区别:

         (1)左值可以被修改右值不可以

         (2)左值可以取地址右值不可以

         (3)普通引用只能引用左值不能引用右值(const引用可以引用左值也可以引用右值)

2.右值引用要想引用左值,必须通过std::move()函数将左值转换为右值。

3.移动语义:将一个对象的资源传递给另一个对象,不需要新开辟空间。

#include<iostream>
using namespace std;
class String
{
public:
	String(const char* str=" ")
	{
		cout << "Create:" << this << endl;
		_str = new char[strlen(str) + 1];
		strcpy_s(_str, strlen(str) + 1, str);
	}
	//移动构造函数
	String(String &&s)
	{
        cout<<"Move Create:<<this<<endl;
        //不需要创建新的空间,直接将空间传递
		_str = s._str;
		s._str = nullptr;
	}
	String(const String& s) :_str(new char[strlen(s._str) + 1])
	{
		cout << "Copy Create:" << this << endl;
		strcpy_s(_str, strlen(s._str) + 1, s._str);
	}
	String operator+(const String& s)
	{
		char* tmp = new char[strlen(_str) + strlen(s._str) + 1];
		strcpy_s(tmp, strlen(_str) + 1, _str);
		strcpy_s(tmp + strlen(_str), strlen(s._str) + 1, s._str);
		String res(tmp);
		return res;
	}
	~String()
	{
		cout << "Free:" <<this<< endl;
		if(_str)
		    delete[] _str;
		_str = nullptr;
	}
private:
	char* _str;
};

int main()
{
	String s1("hello");
	String s2("world");
	String s3(s1 + s2); //hello world
	return 0;
}

       (1)有移动构造函数的运行结果

              

        (2)没有移动构造函数的运行结果

             

4.完美转发

      函数模板在向其他函数传递自身形参时,相应实参为左值就转发为左值,相应实参为右值就转发为右值。要利用forward函数进行实现。

#include<iostream>
using namespace std;
void Fun(int& x)
{
	cout << "lvalue" << endl;
}
void Fun(int&& x)
{
	cout << "rvalue" << endl;
}
void Fun(const int& x)
{
	cout << "const lvalue" << endl;
}
void Fun(const int&& x)
{
	cout << "const rvalue" << endl;
}
template<typename Type>
void PF(Type&& t)
{
	//利用forward函数实现完美转发
	Fun(forward<Type>(t));
}

void main()
{
	PF(10);

	int a = 10;
	PF(a);

	const int& x=10;
	PF(x);

	const int&& y = 10;
	PF(move(y));
}

       运行结果

          

五、lambda表达式

       1.形式:[捕捉列表](参数列表)->返回值类型{函数体}

       2.lambda相当于一种匿名函数,默认情况下是一个const函数

       3.捕获列表说明

           (1)[var]:以传值方式传递捕获的该变量,不可以在lambda函数体内对该值进行修改。

           (2)[=]:以传值方式传递捕获的lambda函数体所在语句块中的所有变量。

           (3)[&val]:以引用方式传递捕获的该变量,可以在lambda函数体内对该变量进行修改,但出了lambda函数体后,该变量并不会被改变。

           (4)[&]以引用方式传递捕获的lambda函数体所在语句块中的所有变量。

           (5)[this]:以传值方式传递捕获的this指针

#include<iostream>
using namespace std;
int main()
{
	int x = 1;
	//最简单的lambda表达式
	[] {};
	//调用方法一
	auto fun = []()->void
	{
		cout << "调用方法一" << endl;
	};
	fun();
	//调用方法二
	[]()->void
	{
		cout << "调用方法二" << endl;
	}();

	int res1 = [](int a, int b)->int
	{
		return a + b;
	}(1, 2);
	cout << "res1 = " << res1 << endl;

	//传值方式传递捕捉的变量
	int res2 = [x]()->int
	{
		return x;
	}();
	cout << "res2 = " << res2 << endl;
	int res3 = [=]()->int
	{
		return x;
	}();
	cout << "res3 = " << res3 << endl;
	//引用方式传递捕捉的值
	int res4 = [&x]()->int
	{
		x = 10;
		return x;
	}();
	cout << "res4 = " << res4 << endl;
	int res5 = [&]()->int
	{
		x = 10;
		return x;
	}();
	cout << "res5 = " << res5 << endl;
	return 0;
}

       运行结果

           

4.仿函数与lambda表达式

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Test
{
public:
	Test(int data = 0) :m_data(data)
	{}
public:
	int m_data;
};

struct my_greater
{
	bool operator()(const Test& t1, const Test& t2)const
	{
		return t1.m_data > t2.m_data;
	}
};

void main()
{
	vector<Test> tv = { 4, 1, 8, 5, 3, 7, 0, 9, 2, 6 };
	//my_greater()仿函数(在类中重载operator()运算符)实现从大到小排序
	sort(tv.begin(), tv.end(), my_greater());
	//lambda表达式实现从大到小排序
	sort(tv.begin(), tv.end(), [](const Test& t1, const Test& t2)->bool {return t1.m_data > t2.m_data; });
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值