C++ 11 的部分新特性

来源:C++Primer 5。

1.long long类型 :长整型,最小尺寸:64位。

2.列表:{}。

         可用来初始化基本数据类型。

         容器(包括关联容器和顺序容器等)可以通过列表初始化、赋值。

         函数可以返回花括号包围的值的列表。

        动态分配对象可以使用列表初始化。

3.nullptr:得到空指针最直接的方法,(等价于0和NULL)NULL是预处理变量(preprocessor variable),在头文件cstdlib中定义。

4.constexpr变量:将变量声明为constexpr类型以便编译器来验证变量的值是否是一个常量表达式。

5.类型别名:是某种类型的别名。传统方法用typedef,新方法用using(别名声明)。

6.auto类型指示符:让编译器通过初始值来推算变量的类型。(用来缩写类型和简化声明)

7.decltype:选择并返回操作数的数据类型。(用来缩写类型、简化声明、简化返回类型定义)

8.类内初始化:可以为类的数据成员提供一个类内初始值(in-class initializer)。创建对象时,类内初始值将被用于初始化数据成员。没有初始值的成员将被默认初始化。

9.范围for语句:  语法形式      expression表示的必须是一个序列,这些类型的共同特点是拥有能返回迭代器的begin和end成员。

for(declaration:expression)
    statement
//等价于
for(auto beg = v.begin(),end = v.end();beg != end;++beg)
{
    auto &r = *beg;
    r *= 2;
}

10.定义vector对象中的vector:

旧式:vector<vector<int> >
新式:vector<vector<int>>

11.容器的cbegin和cend函数:得到const_iterator类型的返回值。

12.标准库begin和end函数:分别返回指向数组首元素的指针,指向数组尾元素的指针。

13.除法的舍入规则:新:一律向0取整。旧:允许结果为负值的商向上或向下取整。

14.用sizeof用于类成员:允许使用作用域运算符获取类成员的大小,如:sizeof(class_name::member_name)。

15.标准库initializer_list类:用于表示某种特定类型的数组,initializer_list对象中的元素永远是常量值,无法改变initializer_list对象中元素的值。

16.可使用尾置返回类型(trailing return type)来简化函数的声明。下面是一个典型例子:

int (*func(int i))[10];
//等价于
auto func(int i) -> int(*)[10];//为了表示函数真正的返回类型跟在形参列表之后,我们在本应该出现返回类型的地方放置一个auto。

17.constexpr函数:指用于常量表达式的函数。需要遵循几项约定:函数的返回类型及所有形参的类型都得是字面值类型,而且函数体中必须有且只有一条return语句。

     constexpr构造函数必须初始化所有数据成员,初始值或者使用constexpr构造函数,或者是一条常量表达式。constexpr构造函数可以被声明成default或delete。

18.使用=default:如果我们需要默认的行为,那么可以通过在参数列表后面写上=default来要求编译器生成默认构造函数。(如果编译器不支持类内初始值,那么默认构造函数应该使用构造函数初始值列表来初始化类的每个成员)同样的可以通过将拷贝控制成员定义为=default来显示地要求编译器生成合成的版本。——我们只能对具有合成版本的成员函数使用=default(即,默认构造函数或拷贝控制成员)。如果我们不希望合成的成员是内联函数,应该只对成员的类外定义使用=default。

19.类对象成员的类内初始化:类内初始值必须使用=的初始化形式或者花括号括起来的直接初始化形式。

20.委托构造函数:产生原因:扩展了构造函数初始值的功能。一个委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程,或者说把它自己的一些(或者全部)职责委托给了其他构造函数。

21.用string对象处理文件名:文件名既可以是库类型string对象,也可以是C风格字符数组。

22.新标准库顺序容器:array、forward_list。

array:固定大小数组。支持快速随机访问。不能添加或删除元素。与内置数组相比,array是一种更安全、更容易使用的数组类型。

forward_list:单向链表。只支持单向顺序访问。在链表任何位置进行插入\删除操作速度都很快。forward_list的设计目标是达到与最好的手写的单向链表数据结构相当的性能。因此forward_list没有size操作,因为保存或计算其大小就会比手写链表多出额外的开销。对其他容器而言,size保证是一个快速的常量时间的操作。

现代C++程序应该使用标准库容器,而不是更原始的数据,如内置数组。是因为新标准库容器的性能几乎肯定与最惊心优化过的同类数据结构一样好(通常会更好)。

23.cbegin,cend:当不需要写访问时使用。

24.容器的非成员函数swap:swap操作交换两个相同类型容器的内容。除array外,交换两个容器内容的操作保证会很快——元素本身并未交换,swap只是交换了两个容器的内部数据结构(我的理解是交换了所指向的地址);与其他容器不同,swap两个array会真正交换它们的元素。因此,交换两个array所需的时间与array中元素的数目成正比;在新标准库中,容器既提供成员函数版本的swap,也提供非成员版本的swap。而早期标准库版本只提供成员函数版本的swap。非成员版本的swap在泛型编程中是非常重要的。统一使用非成员版本的swap是一个好习惯。

25.容器的emplace成员:新标准引入了三个新成员——emplace_front、emplace和emplace_back,这些操作构造而不是拷贝元素。这些操作分别对应push_front、insert和push_back,允许我们将元素放置在容器头部、一个指定位置之前或容器尾部。

26.shrink_to_fit:将capacity()减少为与size()相同大小。(非新标准,capacity():不重新分配内存空间的话,容器可以保存多少元素。reserve(n):分配至少能容纳n个元素的内存空间。

27.string的数值转换函数:

to_string(val)一组重载函数,返回数值val的string表示。val可以是任何算术类型。对每个浮点类型和int或更大的整型,都有相应版本的to_string。与往常一样,小整型会提升。

stoi(s,p,b)

stol(s,p,b)

stoul(s,p,b)

stoll(s,p,b)

stoull(s,p,b)

返回s的起始子串(表示整数内容)的数值,返回值类型分别是int、long、unsigned long、long long、unsigned long long。b表示转换所用的基数,默认值为10。p是size_t指针,用来保存s中第一个非数值字符的下标,p默认为0,即,函数不保存下标。

stof(s,p)

stod(s,p)

stold(s,p)

返回s的起始子串(表示浮点数内容)的数值,返回值类型分别是float、double或long double。参数p的作用与整数转换函数中一样。

28.lambda表达式:一个lambda表达式表示一个可调用的代码单元。我们可以将其理解为一个未命名的内联函数。

[capture list](parameter list) -> return type { function body }
//capture list(捕获列表)是一个lambda所在函数中定义的局部变量的列表(通常为空)
//return type、parameter list、function body与任何普通函数一样,分别表示返回类型、参数列表、函数体。
//lambda必须使用尾置返回来指定返回类型。

29.标准库bind函数:定义在头文件functional中。可以将bind函数看做一个通用的函数适配器,它接收一个可调用对象,生成一个新的可调用对象来”适应“原对象的参数列表。(这个函数和JS中的bind有很大的区别,我的理解:C++中的bind是用来绑定默认实参,而JS中的bind是用来传递this指针

auto newCallable = bind(callable,arg_list);
//newCallable本身是一个可调用对象。
//arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。
//即,当我们调用newCallable时,newCallable会调用callable,并传入给它arg_list中的参数。

30.无序容器:新标准定义了4个无序关联容器(unordered associative container),分别是unordered_set、unordered_map、unordered_multiset、unordered_multimap。这些容器不是使用比较运算符来组织元素,而是使用一个哈希函数(hash function)和关键字类型的==运算符。——如果关键字类型固有就是无序的,或者性能测试发现问题可以用哈希技术解决,就可以使用无序容器。

31.智能指针:新的标准库提供了两种智能指针(smart pointer)类型来管理动态对象,这是为了更容易(同时也更安全)地使用动态内存。这两个指针的区别在于shared_ptr允许多个指针指向同一个对象;unique_ptr则“独占”所指向的对象。(通过英文命名易于理解)标准库还定义了一个名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。

32.auto和动态分配:由于编译器要用初始化器的类型来推断要分配的类型,只有当括号中仅有单一初始化器时才可以使用auto。一个例子:虽然可以用空括号对数组中元素进行值初始化,但不能在括号中给出初始化器,这意味着不能用auto分配数组。

auto p1 = new auto(obj);    //p指向一个与obj类型相同的对象
                            //该对象用obj进行初始化
auto p2 = new auto{a,b,c};  //错误:括号中只能有单个初始化器

//个人尝试:(和{都满足上述结论。

33.范围for语句不能应用于动态分配数组:当用new分配一个数组时,并未得到一个数组类型的对象,而是得到一个数组元素类型的指针。由于分配的内存并不是一个数组类型,因此不能对动态数组调用begin或end。出于相同的原因,也不能用范围for语句来处理(所谓的)动态数组中的元素。——动态数组并不是数组类型。

34.allocator::construct可使用任意构造函数。早期版本的标准库中,construct只接受两个参数:指向创建对象位置的指针和一个元素类型的值。在新标准库中,construct成员函数接受一个指针和零个或多个额外参数,在给定位置构造一个元素。

35.使用=delete阻止拷贝类对象:我们可以通过将拷贝构造函数和拷贝赋值运算符定义为删除的函数(deleted function)来阻止拷贝。

36.用移动类对象代替拷贝类对象:使用名为move的标准库函数,它定义在utility头文件中。

37.右值引用(rvalue reference):所谓右值引用就是绑定到右值的引用。——只能绑定到一个将要销毁的对象。

38.移动构造函数和移动赋值:参数是右值引用,移动操作后,移后源对象必须保持有效的、可析构的状态,但是用户不能对其值进行任何假设。(虽然是书上原话,但是我个人拼接而成)由于移动操作“窃取”资源,它通常不分配任何资源。因此,移动操作通常不会抛出任何异常。故指明noexcept表示该函数不会抛出异常。

39.移动迭代器:通过改变给定迭代器的解引用运算符的行为来适配此迭代器。一般来说,一个迭代器的解引用运算符返回一个指向元素的左值。与其他迭代器不同,移动迭代器的解引用运算符生成一个右值引用。我们通过将调用标准库的make_move_iterator函数将一个普通迭代器转换为一个移动迭代器。此函数接受一个迭代器参数,返回一个移动迭代器。

40.引用限定成员函数:在参数列表后放置一个引用限定符(reference qualifier),引用限定符可以是&或&&,分别指出this可以指向一个左值或右值。(当同时用const和引用限定时,引用限定符必须跟随在const限定符之后)

41.function类模板:解决不同类型具有相同的调用形式的情况。定义在functional头文件中。

42.explicit类型转换运算符:编译器(通常)不会将一个显示的类型转换运算符用于隐式类型转换。

43.虚函数的override指示符:派生类显示地注明它使用某个成员函数覆盖了它继承的虚函数。

44.通过定义类为final来阻止继承。

45.继承的构造函数:派生类继承基类构造函数的方式是提供一条注明了(直接)基类名的using声明语句。

46.声明模板类型形参为友元。

47.模板类型别名:可以定义一个typedef来引用实例化的类。由于模板不是一个类型,我们不能定义一个typedef引用一个模板。

48.模板函数的默认模板参数:我们可以为函数和类模板提供默认实参,无论何时使用一个类模板,我们都必须在模板名之后接上尖括号。尖括号指出类必须从一个模板实例化而来。

49.实例化的显示控制:为了解决在多个文件中实例化相同模板的额外开销可能非常严重。在新标准中我们可以通过显示实例化(explicit instantiation)来避免这种开销。

//显示实例化形式
extern template declaration;   //实例化声明
template declaration;          //实例化定义

50.引用折叠规则:在新标准中,折叠规则扩展到右值引用。只在一种特殊情况下引用会折叠乘右值引用:右值引用的右值引用。

51.用static_cast将左值转换为右值:虽然不能隐式地将一个左值转换为右值引用,但我们可以用static_cast显式地将一个左值转换为一个右值引用。

52.标准库forward函数:与move不同,forward必须通过显式模板实参来调用。forward返回该显式实参类型的右值引用。即forward<T>的返回类型是T&&。目的:保持原始实参的类型。

53.可变参数模板。

//例
template <typename T,typename ... Args>
void foo(const T &t,const Args& ...rest);

54.sizeof...运算符:求包中有多少元素。

55.新标准库tuple类模板:可以将tuple看作一个“快速而随意”的数据结构。使用场景:当我们希望将一些数据组合乘单一对象,但又不想麻烦地定义个新数据结构来表示这些数据时。

56.正则表达式库:定义在头文件regex中。regex类表示一个正则表达式。除了初始化和赋值之外,regex还支持其它一些操作。

57.随机数库:随机数引擎类(random-number engines)和随机数分布类(random-number distribution)。定义在头文件random中。

58.浮点数格式控制:hexfloat(浮点值显示为十六进制)、defaultfloat(重置浮点数格式为十进制)

59.noexcept异常指示符,noexcept运算符:提供noexcept说明(noexcept specification)指定某个函数不会抛出异常。noexcept运算符是一个一元运算符,它的返回值是一个bool类型的右值常量表达式,用于表示给定的表达式是否会抛出异常。

60.内联命名空间:和普通的嵌套命名空间不同,内联命名空间中的名字可以被外层命名空间直接使用。定义内联命名空间的方式是在关键字namespace前添加关键字inline。

61.继承的构造函数和多重继承:允许派生类从它的一个或几个基类中继承构造函数。但是如果从多个基类中继承了相同的构造函数(即形参类型完全相同),则程序将产生错误。所以如果发生这个情况,这个类必须为该构造函数定义它自己的版本。

62.有作用域的enum:定义限定作用域的枚举类型的一般形式是:首先是关键字enum class(或者等价地使用enum struct),随后是枚举类型名字以及花括号括起来的以逗号分隔的枚举成员列表,最后是一个分号。

enum class open_modes{input,output,append};

63.enum的前置声明:我们可以提前声明enum。enum的前置声明(无论隐式地还是显示地)必须指定其成员的大小。

64.标准库mem_fn类模板:定义在functional头文件中,让编译器负责推断成员的类型。从成员指针生成一个可调用对象。

65.类类型的union成员:在union中可以含有定义了构造函数或拷贝控制成员的类类型成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值