C++版本发展简史:新特性介绍

简介

  C++是一门以C为基础发展而来的一门面向对象的高级程序设计语言,从1983年由Bjarne Stroustrup教授在贝尔实验室创立开始至今,已有30多个年头。C++从最初的C with class,经历了从C++98、C++ 03、C++ 11、C++ 14、C++17再到C++ 20多次标准化改造,功能得到了极大的丰富,已经演变为一门集面向过程、面向对象、函数式、泛型和元编程等多种编程范式的复杂编程语言。
在这里插入图片描述

在这里插入图片描述

1、C++ 98

  1998年,C++标准委员会统筹C++的所有特性,发布了第一个C++国际标准C++98。

2、C++ 03

  从1998年到2003年,是C++标准从C++98到C++03的迭代期,期间C++扩增了很多额外的特性,比如以Boost MPL(Boost Metaprogramming Library)与Loki等为代表的模板元编程库的出现,让开发者更加便捷的使用C++在编译期的执行能力,即通过代码编译获得计算结果,学术性的称为模板元编程。到了2003年,C++标准委员会总结最新技术并发布了C++03标准。C++03 是给 C++98 打的补丁,所以现在的人提到 C++98, C++03 往往指的是同一个。

3、C++ 11

  从2003年到2011年,也就是从C++03到C++11,期间C++引入了对象移动、右值引用、lamba表达式(函数式编程)、编译时类型识别(auto)、别名模板以及很多新型关键词(如nullptr、decltype、constexpr)等现代编程语言常具备的能力,让C++与时俱进,开发效率得到了很大的提升。这些新的特性随着C++11标准的发布而被正式确立下来。C++ 11版本也被称为现代C++,而C++ 98/03版本也被称为传统C++。

3.1 nullptr

  由于 C++ 98 标准使用期间,NULL 已经得到了广泛的应用,出于兼容性的考虑,C++11 标准并没有对 NULL 的宏定义做任何修改。为了修正 C++ 存在的这一 BUG,C++ 标准委员会最终决定另其炉灶,在 C++11 标准中引入一个新关键字,即 nullptr。nullptr 是 nullptr_t 类型的右值常量,专用于初始化空类型指针。nullptr_t 是 C++11 新增加的数据类型,可称为“指针空值类型”。也就是说,nullpter 仅是该类型的一个实例对象(已经定义好,可以直接使用),如果需要我们完全定义出多个同 nullptr 完全一样的实例对象。nullptr 可以被隐式转换成任意的指针类型。举个例子:

 int * a1 = nullptr;
char * a2 = nullptr;
double * a3 = nullptr;

3.2 auto

  在之前的 C++ 版本中,auto 关键字用来指明变量的存储类型,它和 static 关键字是相对的。auto 表示变量是自动存储的,这也是编译器的默认规则,所以写不写都一样,一般我们也不写,这使得 auto 关键字的存在变得非常鸡肋。C++11 赋予 auto 关键字新的含义,使用它来做自动类型推导。也就是说,使用了 auto 关键字以后,编译器会在编译期间自动推导出变量的类型,这样我们就不用手动指明变量的数据类型了。auto 关键字基本的使用语法如下:

auto name = value;
int  x = 0;
auto *p1 = &x;   //p1 为 int *,auto 推导为 int
auto  p2 = &x;   //p2 为 int*,auto 推导为 int*
auto &r1  = x;   //r1 为 int&,auto 推导为 int
auto r2 = r1;    //r2 为  int,auto 推导为 int

  name 是变量的名字,value 是变量的初始值。注意:auto 仅仅是一个占位符,在编译器期间它会被真正的类型所替代。或者说,C++ 中的变量必须是有明确类型的,只是这个类型是由编译器自己推导出来的。

auto 的限制:

  • 使用 auto 的时候必须对变量进行初始化
  • auto 不能在函数的参数中使用
  • auto 不能作用于类的非静态成员变量

auto 关键字不能定义数组,如比如下面的例子就是错误的:

char url[] = "http://c.biancheng.net/";
auto  str[] = url;  //arr 为数组,所以不能使用 auto

auto 不能作用于模板参数

3.3 decltype

  decltype 是 C++ 11新增的一个关键字,它和 auto 的功能一样,都用来在编译时期进行自动类型推导。既然已经有了 auto 关键字,为什么还需要 decltype 关键字呢?因为 auto 并不适用于所有的自动类型推导场景,在某些特殊情况下 auto 用起来非常不方便,甚至压根无法使用,所以 decltype 关键字也被引入到 C++11 中。auto 和 decltype 关键字都可以自动推导出变量的类型,但它们的用法是有区别的:

 auto varname = value;
decltype(exp) varname = value;

  其中,varname 表示变量名,value 表示赋给变量的值,exp 表示一个表达式。auto 根据=右边的初始值 value 推导出变量的类型,而 decltype 根据 exp 表达式推导出变量的类型,跟=右边的 value 没有关系。另外,auto 要求变量必须初始化,而 decltype 不要求。这很容易理解,auto 是根据变量的初始值来推导出变量类型的,如果不初始化,变量的类型也就无法推导了。decltype 可以写成下面的形式:

  decltype(exp) varname;

  原则上讲,exp 就是一个普通的表达式,它可以是任意复杂的形式,但是我们必须要保证 exp 的结果是有类型的,不能是 void;例如,当 exp 调用一个返回值类型为 void 的函数时,exp 的结果也是 void 类型,此时就会导致编译错误。C++ decltype 用法举例:

int a = 0;
decltype(a) b = 1;  //b 被推导成了 int
decltype(10.8) x = 5.5;  //x 被推导成了 double
decltype(x + 100) y;  //y 被推导成了 double

3.4 初始化列表

(1)一致性初始化
  在 C++ 98/03 中的对象初始化方法有很多种,包括小括号,大括号和赋值操作符,这些不同的初始化方法,都有各自的适用范围和作用。最关键的是,这些种类繁多的初始化方法,没有一种可以通用所有情况。为了统一初始化方式,并且让初始化行为具有确定的效果,C++11 引入了“一致性初始化”的概念,意思是对任何初始化动作,你可以使用相同的语法,也就是使用大括号。

int values[]{
   
   1, 2, 3};
std::vector<int> v {
   
   2, 3, 5, 7, 11, 13, 17};
std::vector<std::string> cities {
   
   "bejing", "shanghai", "guangzhou", "shenzhen"};

(2)初始列
  初值列会强迫造成所谓的value initialization,意思是即使某个局部变量属于某个基础类型,也会被初始化为0或者nullptr(如果它是个指针的话):

int i;     // i是随机值
int j{
   
   };   // j初始化为0
int* p;    // p是未定义值
int* q{
   
   };  // q初始化为nullptr

3.5 范围for循环

  C++ 11 标准中,除了可以沿用前面介绍的用法外,还为 for 循环添加了一种全新的语法格式,如下所示:

for (declaration : expression)
{
   
   
    //循环体
}

其中,两个参数各自的含义如下:

  • declaration:表示此处要定义一个变量,该变量的类型为要遍历序列中存储元素的类型。需要注意的是,C++ 11标准中,declaration参数处定义的变量类型可以用 auto 关键字表示,该关键字可以使编译器自行推导该变量的数据类型。
  • expression:表示要遍历的序列,常见的可以为事先定义好的普通数组或者容器,还可以是用 {} 大括号初始化的序列。

3.6 右值引用

(1)左值和右值
  在 C++ 或者 C 语言中,一个表达式(可以是字面量、变量、对象、函数的返回值等)根据其使用场景不同,分为左值表达式和右值表达式。确切的说 C++ 中左值和右值的概念是从 C 语言继承过来的。左值的英文简写为“lvalue”,右值的英文简写为“rvalue”。很多人认为它们分别是"left value"、“right value” 的缩写,其实不然。lvalue 是“loactor value”的缩写,可意为存储在内存中、有明确存储地址(可寻址)的数据,而 rvalue 译为 “read value”,指的是那些可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据)。

通常情况下,判断某个表达式是左值还是右值,最常用的有以下 2 种方法:

  • 可位于赋值号(=)左侧的表达式就是左值;反之,只能位于赋值号右侧的表达式就是右值。
  • 有名称的、可以获取到存储地址的表达式即为左值;反之则是右值。

(2)右值引用
  C++98/03 标准中就有引用,使用 “&” 表示。但此种引用方式有一个缺陷,即正常情况下只能操作 C++ 中的左值,无法对右值添加引

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

欧特克_Glodon

很高兴能帮助到您!

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

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

打赏作者

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

抵扣说明:

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

余额充值