C++11新特性

C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅
功能更强大,而且能提升程序员的开发效率。

1、列表初始化

在C++98中可以对数组元素进行列表初始化,但是对一些自定义的类型无法用 这样的方法初始化,例如

int arr[]={1,2,3,4,5};
vector<int> v{1,2,3,4,5};//C++98不支持这样初始化,C++11支持

所以C++11提供了统一的语法可以初始化任意对象。

C++11支持单个对象列表初始化,但是多个对象想要支持列表初始化,需给该类(模板类)添加一个带有initializer_list 类型参数的构造函数即可。注意:initializer_list是系统自定义的类模板,该类模板中主要有三个方法:begin()、end()迭代器以及获取区间中元素个数的方法size()。

#include <initializer_list>
template<class T>
class Vector 
{
public:
// ...
	Vector(initializer_list<T> l): _capacity(l.size()), _size(0)
	{
		_array = new T[_capacity];
		for(auto e : l)
		_array[_size++] = e;
	}
	
	Vector<T>& operator=(initializer_list<T> l) 
	{
		delete[] _array;
		size_t i = 0;
		for (auto e : l)
		_array[i++] = e;
		return *this;
	}
// ...
private:
	T* _array;
	size_t _capacity;
	size_t _size;
};
2、变量类型推导
2.1 auto类型推导

在定义变量时需要先给出实际的变量类型,但是有时候不确定变量或变量类型比较复杂,就可以使用auto根据变量初始化表达式类型推导变量的实际类型,这样既简洁又方便。

#include <map>
#include <string>

int main()
{
	//1、不确定变量的类型
	short a = 32670;
	short b = 32670;
	
	short c = a + b;//数据溢出
	auto d = a + b;//结果正确
	
	//2、变量类型复杂
	std::map<std::string, std::string> m{{"apple", "苹果"}, {"banana","香蕉"}};
	
	// 使用迭代器遍历容器, 迭代器类型太繁琐
	//std::map<std::string, std::string>::iterator it = m.begin();
	auto it = m.begin();
	while(it != m.end())
	{
		cout<<it->first<<" "<<it->second<<endl;
		it++;
	}
	return 0;
}

auto使用细则

  • auto与指针和引用结合起来使用
    用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
  • 在同一行定义多个变量
    当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量

auto使用的前提是:必须对auto声明的类型进行初始化,否则不能推导出auto的实际类型。
所以需要decltype类型推导,decltype是根据表达式的实际类型推演出定义变量时所用的类型。

2.2 decltype类型推导

应用场景:需要根据表达式运行完成之后的结果进行类型推导,这时候不能使用auto,而是需要decltype类型推导。

decltype是根据表达式的实际类型推演出定义变量时所用的类型。

  • 推演表达式类型作为变量的定义类型
  • 推演函数返回值的类型
3、范围for

先看一个例子来认识一下范围for的语法

int arr[] = {1,23,4};

//for循环遍历
int len = sizeof(arr)/sizeof(arr[0]);
for(int i = 0; i < len; i++)
{
	cout<<arr[i]<<" ";
}
cout<<endl;

//范围for遍历
for(auto &e:arr)
{
	cout<<e<<" ";
}
cout<<endl;

有上面的例子可知,范围for的组成:for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。其他用法与正常的for用法相同。

范围for的使用条件

  • for循环的迭代范围必须确定
    对于数组来说,必须知道第一个元素与最后一个元素的范围;对于类来说,必须知道begin和end.
  • 迭代的对象要实现++和==的操作
4、final和override
  1. final
    不希望虚函数被继承或重写,在类名和虚函数后面加上final关键字,如果进行重写或继承则会报错。
class TestBase
{
	virtual void test() final;//虚函数test不可以被重写
}
class Test final: public TestBase//Test类不能被继承
{
	virtual void test();//编译出错,有final关键字表示test函数不能被重写
}
class Test2 : public Test//编译出错,Test不能被继承
{
}
  1. override
    需要被重写的虚函数可以加上override,如果出现错误,在编译的时候会报错;如果没有加上override,在重写虚函数的时候出错不会报错,为了方便建议在需要重写虚函数的时候加上override.
class TestBase
{
	virtual void foo();
}

class Test : public TestBase
{
	virtual void fo0();//存在函数名出错的情况,此时编译通过
	virtual void fo0() override;//此时编译不通过
}
5、智能指针

智能指针的详细内容,请查看我的另一篇博客。
C++智能指针总结

6、新增容器
6.1 array

array与数组类似,保存在栈内存中,相较于保存在堆内存的vector,访问元素更加灵活,所以在访问元素时性能更高。
array 会在编译时会创建一个固定大小的数组,并且array 不能够被隐式的转换成指针,使用array只需指定其类型和大小。

6.2 forward_list

forward_list与list相似,不同的是list是双向链表,而forward_list是单向链表,只能朝前迭代,所以可以以O(1)的时间复杂度进行插入,但是不支持随机存取。

6.3 无序容器

无序容器有unordered_map/unordered_multimap 、unordered_set/unordered_multiset

容器内部不进行排序,底层是通过Hash实现的。

7、 委派构造函数

委派构造函数的目的也是为了减少程序员书写构造函数的时间。通过委派其他构造函数,多构造函数的类编写更加容易。

class Info{
public:
	// 目标构造函数
	Info():
	  _type(0),
	  _a('a')
	{ 
		InitRSet();
	}
	// 委派构造函数
	Info(int type): Info()
	{ 
		_type = type;
	}
	// 委派构造函数
	Info(char a): Info()
	{ 
		_a = a;
	}
private:
	void InitRSet()
	{ //初始化其他变量 }
private:
	int _type = 0;
	char _a = 'a';
	//...
};

在初始化列表中调用”基准版本”的构造函数称为委派构造函数,而被调用的”基准版本”则称为目标构造函数。
注意:构造函数不能同时”委派”和使用初始化列表。

8、默认函数控制

在C++中对于空类编译器会生成默认成员函数,如果在类中显示定义了,编译器就不会产生,这样就会容易混淆,到底有没有默认的成员函数,所以在C++11中让程序员自己控制是否需要编译器生成默认的成员函数。

8.1 显示缺省函数

在C++11中,可以在默认函数定义或者声明时加上=default,从而显式的指示编译器生成该函数的默认版本,用=default修饰的函数称为显式缺省函数。

class A
{
public:
	A(int a): _a(a)
	{}
	// 显式缺省构造函数,由编译器生成
	A() = default;
	// 在类中声明,在类外定义时让编译器生成默认赋值运算符重载
	A& operator=(const A& a);
private:
	int _a;
};
8.2 删除默认函数

如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且不给定义,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。

9、右值引用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值