c++11特性

一、新类型

  1. long long和unsigned long long,支持64位整型。
  2. char16_t和char32_t,支持16位和32位的字符表示。
  3. 新增了“原始”字符串。

二、统一的初始化

c++11扩大了用·大括号括起的列表的适用范围,使其可适用所有内置类型和用户定义的类型(类对象)。

  1. 初始化列表,可添加等号(=),也可不添加。int x={5};double y{2.75}; short quar[5] {4,5,2,76,1};
  2. 创建对象时,可使用大括号括起列表来调用构造函数。class Stump{private:int roots;double wight;public:Stump(int r,double w):roots(r),weight(w){}};Stump s1(3,15.6); //老式 Stump s2{5,43.4};//c++11 Stump s3={4,32.1};c++11如果类有模板initializer_list作为参数的构造函数,则只有该构造函数可以使用列表初始化形式

三、缩窄

初始化列表语法可防止缩窄,即禁止将数值赋给无法存储它的数值变量。常规初始化允许程序执行可能没有意义的操作:

char c1 = 1.57e27;//double到char 未定义的行为
char c2 = 459585821;//int到char 未定义的行为

如果使用初始化列表语法,编译器将禁止进行这样的类型转换,即将值存储到比它“窄”的变量中:

char c1{
   1.57e27};//double到char,编译出错
char c2={
   459585821};//int到char,超出范围出错

但允许转换为更宽的类型。另外,只要值在较窄类型的取值范围内,将其转换为较窄的类型是允许的:

char c1{
   66};//在范围内,允许
double c2={
   66};//int 到double,允许

四、initializer_list

c++11提供了模板类initializer_list,可将其用作构造函数的参数。如果类有接受initializer_list作为参数的构造函数,则初始化列表语法就只能用于该构造函数。列表中的元素必须是同一种类型或可转换为同一种类型。STL容器提供了将initializer_list作为参数的构造函数:

vector<int>a1(10);//包含10个元素的未初始化变量
vector<int>a2{
   10};//初始值设定-lsit,a2有个元素设置为10
vector<int>a3{
   4,6,1};//3个元素被设置为4,6,1

头文件initializer_list提供了对模板类initializer_list的支持。这个类包含成员函数begin()和end(),可用于获悉列表的范围。除用于构造函数外,还可将initializer_list用作常规函数的参数:

#include<iostream>
#include<initializer_list>
using namespace std;
double sum(initializer_list<double> il);

int main()
{
   
    double total=sum({
   2.5,3.1,4});//4转变4.0
    ...
}
double sum(initializer_list<double> il)
{
   
    double tot=0;
    for(auto p=il.begin();p!=il.end();p++)
        tot+=*p;
    return 0;
}

五、声明

c++11提供了多种简化声明的功能,尤其在使用模板时。

  1. auto;存储类型说明符,c++11将其用于自动类型推断。要求进行显示初始化。 auto maton=112;//int auto pt=&maton;//int * double fm(double int); auto pf=fm;//pf=double(*)(double,int);还可以简化模板声明,il为initializer_lsit对象,代码为:for(initialzier_list<double>::iterator p=il.begin();p !=il.end();p++)替换为:for(auto p=il.begin();p !=il.end();p++)

  2. decltype将变量的类型声明为表达式指定的类型。例:让y类型与x相同,其中x是个表达式:decltype(x) y;这在定义模板时特别有用,因为只有等到模板被实例化才能确定类型:template<typename T,typename U) void ef(T t,U u){decltype(T*U) tu;...}tu为表达式T*U的类型,如果T为char,U为short,则tu为int,这是由整型算术自动执行整型提升导致的。还可以指定类型为引用和const例:int j=3;int &k=j;const int &n=j;decltype(n) i1;//il为const int & decltype(j) i2;//i2为int decltype((j)) i3;//i3为int & decltype(k+1) i4;//i4为int

六、返回类型后置

c++11新增了一种函数声明语法:在函数名和参数列表后面(而不是前面)指定返回类型:

double f1(double,int);//传统语法
auot f2(double,int)->double;//新语法,返回类型double

常规函数的可读性而言,这种语法好像是倒退,但能使用decltype来指定模板函数的返回类型:

template<typename T,typename U)
auto eff(T t,U u)->decltype(T*U){
   ...}

这里解决的问题是,在编译器遇到eff的参数列表前面,T和U还不在作用域内,因此必须在参数列表后使用decltype。这种新语法使得能够这样做。

七、模板别名:using =

对于冗长或复制的标识符,如果能够创建其别名将很方便。以前,c++为此提供typedef:

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

c++11提供了另一种创建别名的语法。:

using itType = vector<string>::iterator;

差别在于,新语法也可用于模板部分具体化,但typedef不能:

template<typename T>
using arr12=array<T,12>;//多个模板别名

上述语句具体化模板array<T,int>,例如,对于下述声明:

array<double,12>a1;
array<string,12>a2;

可将它们替换为下面声明:

arr12<double> a1;
arr12<string> a2;

八、nullptr

空指针是不会指向有效数据的指针,以前,c++在源代码中使用0表示这种指针,但内部表示可能不同。有个问题,因为这使得0即可表示指针常量,也可表示整数常量。c++11新增了关键字nullptr,用于表示空指针;它是指针类型,不能转换为整数类型。但c++11仍允许使用0表示空指针,因此表达式nullptr==0为true,但使用nullptr而不是0提供更高的类型安全。例如:可将0传递给接受int参数的函数,但如果试图将nullptr传递给这样的函数,编译器将此视为错误。所以应使用nullptr。

九、智能指针

9.智能指针
使用new从堆分配内存,不需要时应使用delete将其释放。c++11引入智能指针auto_ptr,帮助自动完成这个过程。c++11 摒弃了auto_ptr,并新增了三种智能指针:unique_ptr、shared_ptr和weak_ptr。

十、异常规范方面的修改

以前,c++提供了一种方法,可用于指出函数可能引发那种异常:

void f501(int) throw(bad_dog);
void f733(long long) throw();

与auto_ptr一样,c++编程社区的集体经验表明,异常规范的效果没有预期的好,因此,c++11摒弃的异常规范。然而,标准认为,指出函数不会引发异常有一定的价值,所以添加了:noexcept:

void f875(short,shortnoexcept;

十一、作用域内枚举

传统的c++枚举提供了一种创建名称常量的方式,但其类型检查相当低级。枚举名的作用域为枚举定义所属的作用域,但如果在同一个作用域内定义两个 枚举,它们的枚举成员不能同名。枚举可能不是可完全移植的,因为不同的实现可能选择不同的底层类型。所以,c++11新增一种枚举,使用class或struct定义:

enum  0ld1{
   yes,no,maybe};
enum class New1{
   never,sometimes,often,always};
enum struct New2{
   never,lever,sever};

新枚举要求进行显示限定 ,以免发生名称冲突。因此,引用特定枚举时,需要使用New1::never和New2::never等。

十二、对类的修改

1.显示转换运运算符

c++支持对象自动转换。但自动转换可能导致意外转换的问题。为解决问题,c++引入了关键字explicit,以禁止单参数构造函数导致自动转换:

class Plebe
{
   
	Plebe(int);//自动int-to-plebe转换
	explicit Plebe(double);//需要显示转换
	...
	};
	Plebe a,b;
	a=5;//隐式转换,调用Plebe(5)
	b=0.5;//不允许
	b=Plebe(0.5);//显示转换

c++11拓展了explicit的这种用法,使得可对转换函数做类似的处理:

class Plebe
{
   
...
//转换函数
	operator int()const;
	explicit operator double() const;
	...
	};
Plebe a,b;
int n=a;//int-to-plebe自动转换
double x=b;//不允许
x=double(b);//允许显示转换

2.类内成员初始化

class Session
{
   
int mem1=10;//类内初始化
double mem2{
   1966.54};//类初始化
short mem3;
public:
Session(){
   }
Session(short s):mem3(s){
   }
Session(int n,double d,short s):mem1(n),mem2(d),mem3(s){
   }
...
};

可使用等号或大括号版本的初始化,但不能使用圆括号版本的初始化。其结果与给前两个构造函数提供成员初始化列表,并指定mem1和mem2的值相同:

Seeion():mem1(10),mem2(1966.54){
   }
Seeion(short):mem1(10),mem2(1966.54),mem3(s){
   }

通过使用类内初始化,可避免在构造函数中编写重复的代码,从而降低工资量。
如果构造函数在成员初始化列表提供了相应的值,这些默认值将被覆盖,因此第三个构造函数覆盖了类内成员初始化。

十三、模板和STL方面的修改

1.基于范围的for循环
对于内置数组以及包含方法begin()和end()的类和STL容器,基于范围的for循环可简化。例:循环对数组或容器中每个元素执行指定的操作

double prices[5]={
   4.99,10.99,6.87,7.99,8.49};
for(double x :prices)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值