【探讨C++新标准】——C++ Prime Plus CH18

1.复习前边介绍的C++11功能

1.1新类型

C++11新增了类型 long long 和 unsigned long long 以支持64位或更宽的整型;新增了char16_t和char32_t,支持16位和32位的字符表示,新增了“原始”字符串。

原生字符串(Raw String)指不进行转义“所见即所得”的字符串。

C++的语法格式如下:
(1)字符串前加R前缀;
(2)字符串首尾加上小括号;

string path = R"(this "word" is escaped)";
#include<iostream>
#include<string>

using namespace std;
int main()
{
	string s1= "this \"word\" is escaped";
	string s2 = R"(this \"word\" is escaped)";

	cout << "s1 " << s1 << endl;
	cout << "s2 " << s2 << endl;
}

1.2统一的初始化

C++扩大了用大括号括起来的列表(初始化列表)的适用范围,可使其用于所有内置类型和用户定义的类型(即类对象),还可以用于new表达式。使用初始化列表的时候,可以加等号,也可以不加等号。

初始化列表语法可防止缩窄,禁止将数值赋给无法存储它的数值变量(值对就可以,double 到char 也行的),但允许转换为更宽的类型。

如果类模板有将模板std::initializer_list作为参数的构造函数,则只有该构造函数可以使用列表初始化,列表中的元素必须是同一种类型或可转换为同一种类型。STL提供了将initializer_list作为参数的构造函数。头文件initializer_list提供了对模板类initializer_list的支持。这个类包含了成员begin()和end(),可以直到列表的范围。除用于构造函数外,还可将initializer_list用于常规函数的参数。

std::initialzer-list可以接受任意长度的同类型的数据也就是接受可变长参数{...}.对于这种拥有固定数目的数据成员来说使用std::initialzer-list来改写后,如果列表初始化的参数刚好是3个则数据成员完全初始化,如果列表初始化的个数小于3个则未给予的值是一个随机值,而大于3个的话超出的列表初始化参数将被抛弃。虽然std::initialzer-list可以改写我们自定义的类,但是对于用于固定的数据成员的类来说这种改写意义不大,若列表初始化个数少于数据成员个数则会导致某些数据成员未被初始化,容易引起程序出BUG.所以,这种固定数据成员的就不太适用,因此在以后碰到需要使用可变长度的同类型的数据时,可以考虑使用std::initialzer-list。
initializer_list对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值。并且,拷贝或赋值一个initializer_list对象不会拷贝列表中的元素,其实只是引用而已,原始列表和副本共享元素。

(建议知道这个就好,2022年了,11标准已经是很老的了)

1.3声明

1.3.1auto声明

auto实现自动类型推断,这要求进行显式初始化。

1.3.2decltype

关键字decltype将变量的类型声明为表达式指定的类型,根据使用的表达式,指定的类型可以为引用和const。

decltype(x)  y;——让y的类型与x 相同

在定义模板时特别有用,因为只有等到模板被实例化时才能确定类型。

1.3.3返回类型后置

在函数名和参数列表后面指定返回类型,能够使用decltype来指定模板函数的返回类型,因为在遇到参数列表前,类型还不在作用域中,因此必须在参数列表后使用decltype。

template<typename T,typaname U>

auto eff(T t,U u) ->decltype(T*U)

{...}

1.3.4模板别名

以前,c++提供了typedef:

typedef std::vector<std::string>::iterator itType;

现在提供了using:

using itType = std::vector<std::string>::iterator ;

差别在于,using也可用于模板部分具体化,typedef不能:

template<typename T>

using arr12 = std::array<T,12>; 

arr12<double> a1;

1.3.5nullptr

空指针,是指针类型,不能转换为整型类型。 

1.4智能指针

C++引入智能指针,可以自动完成对于new分配的内存进行delete过程,特别是在STL编程中。新增三种智能指针为unique_ptr、shared_ptr、weak_ptr。

1.5异常规范方面的修改

异常规范指出函数可能引发哪些异常,但是与其规范效果不好,但仍然保留了noexcept关键字来指出函数不会引发异常。

1.6作用域内枚举

传统C++枚举提供了创建名称常量的方式,但作用域的问题以及枚举可能不是可完全移植的(不同的实现选择不同的底层类型),C++新增了使用class或struct定义的枚举:

enum Old1{yes,no,maybe};

enum class New1{never,sometimes,often,always};

enum struct New2{never,lever,sever};

新枚举要求进行显式限定,以免发生名称冲突。 

1.7对类的修改

1.7.1显式转换运算符

C++引入关键字explicit,以禁止单参数构造函数导致的自动转换,如果需要转换,显式使用关键字来进行转换。C++11扩展了explicit的用法,使得可对转换函数做类似的处理,需要转换,请使用显式类型转换。

1.7.2类内成员初始化

可以在类定义中使用大括号版本初始化,不能使用圆括号版本初始化,其结果与给构造函数提供成员列表初始化作用相同,如果构造函数在成员列表中提供了相应的值,默认值(类定义初始化的值)会被覆盖掉。

1.8模板和STL方面的修改

1.8.1基于范围的for循环

double prices[5] = {44.5 ,56.7,34.7,56.9,34.8};

for(auto x:prices)

std::cout<<x<<std::endl;

1.8.2新的STL容器

新增了单项列表,其他三种新增的列表由哈希表实现的。

1.8.3新的STL方法

新增了cbegin()和cend(),同样的多了 crbegin()和crend().

1.8.4valarray升级

valarray独立于stl开发,C++11新增了begin()和end(),它们都接受valarray作为参数,并返回迭代器,使得能够将基于范围的STL算法用于valarray。

1.8.5摒弃export

6.尖括号

避免与>>运算符混淆,之前要求声明嵌套模板要用空格价格尖括号分开,现在不需要这样。

vector<list<int>> v1;

1.9右值引用

1.9.1左值和右值的概念

C++中左值(lvalue)和右值(rvalue)是比较基础的概念,虽然平常几乎用不到,但C++11之后变得十分重要,它是理解 move/forward 等新语义的基础。

左值与右值这两个概念是从 C 中传承而来的,左值指既能够出现在等号左边,也能出现在等号右边的变量;右值则是只能出现在等号右边的变量。

int a; // a 为左值
a = 3; // 3 为右值
  • 左值是可寻址的变量,有持久性;
  • 右值一般是不可寻址的常量,或在表达式求值过程中创建的无名临时对象,短暂性的。

左值和右值主要的区别之一是左值可以被修改,而右值不能。

1.9.2左值引用和右值引用

  • 左值引用:引用一个对象;
  • 右值引用:就是必须绑定到右值的引用,C++11中右值引用可以实现“移动语义”,通过 && 获得右值引用。
int x = 6; // x是左值,6是右值
int &y = x; // 左值引用,y引用x

int &z1 = x * 6; // 错误,x*6是一个右值
const int &z2 =  x * 6; //
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值