C++11新特性1

C++11中增加了一些新的特性,需要在vs2011(或Linux g++4.8,编译时需要加-std=c++11)之后的版本中才可进行语法解析。

1、nullptr常量

nullptr的出现是为了替换NULL,nullptr是一种特殊类型的字面值,可以被转换成任意的其他类型的指针。

传统的C++,NULL和0的意义是一样的。有些编译器会将NULL定义为((void*)0),有的编译器会将NULL定义为0.

NULL在重载中有可能会发生混乱,比如:

//当NULL被定义为((void*)0),fun(NULL)会调用下列函数
void fun(int*);

//当NULL被定义为0时,fun(NULL)会调用下列函数
void fun(int);

在C++11中引入nullptr来区分空指针和0. nullptr就是一个空指针。它的类型为nullptr_t,能隐式的转换为任何指针的类型。

2、自动类型推导

C++11中引入了auto和decltype这两个关键字来进行类型的推导。在讲解auto时,在加入for循环和typeid操作符的讲解。

auto

auto关键字可以通过初始值,进行类型的自动推导。

语法:auto 变量名 = 初始值     auto是根据初始值的类型来推导变量的类型的,所以初始值不能少。

基本用法:

auto b = 11; //auto推导为int
auto d;      //编不过,无法推演

int x = 10;
auto a = &x;  //推导出a的类型为int*,auto--->int*
auto* b = &x; //b--->int*,auto--->int,支持但不提倡这种写法
auto& c = x;  //c--->int&,auto--->int
auto d = x;
cout << typeid(a).name() << endl; //输出变量a的类型
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;

使用auto来推导迭代器:

//字典
map<string,string> dict{{"cat","猫"},{"word","单词"}};
map<string ,string>::iterator dit = dict.begin();
while(dit != dict.end())
{
    cout << dict->first << ":" << dict->second << " ";
}
cout << endl;

//使用auto简化语法:更简洁
auto dit2 = dict.begin();
while(dit2 != dict.end())
{
    cout << dict->first << ":" << dict->second << " ";
}
cout << endl;

//for循环和auto搭配只用
for(auto kv : dict)  
    cout << kv.first << ":" << kv.second << " ";
cout << endl;

const属性auto声明不能带来:如果使用指针更改了const变量x的值,auto进行类型推演的时候,只能根据编译器的优化,得到更改前的x的值。

const int x = 10; //x:10
int* p = (int*)&x;
*p = 20;   //此时内存中x已经为20
cout << x << endl;  //x=10,输出的是寄存器中的值

auto y = x;  //y=10
int* pp = (int*)&y;
*pp = 30;
cout << y << endl; //30

x输出为10的要点:const修饰的变量,编译器进行优化,放在了寄存器中,编译器认为const修饰的变量是不会变的。但实际上可以通过指针进行改变,写为const只是对程序员的警告,这个变量是不能去改的。通过指针p将x改为了20,此时使用监视窗口发现x的值已经为20了,但编译器的优化在于,输出时输出的是寄存器中的const变量x的值,编译器认为这样是快的。

 

volatile属性auto声明可以带来:volatile关键声明寄存器变量,防止编译器进行优化。使用volatile声明的const变量,使用指针更改值后,编译器不进行优化,输出内存中的值,从而输出结果为20.

使用auto对volatile声明的变量进行推演的时候,得到的是x更改后的值。

volatile const int x = 10; 
int* p = (int*)&x;
*p = 20;
cout << x << endl; //x=20,volatile声明的变量,防止编译器进行优化,输出的是内存中的值

auto y = x;  //y = 20
cout << y << endl;
int* pp = (int*)&y;
*pp = 30;
cout << y << endl;  //y = 30

auto不能推导的场景:

  •     auto不能作为函数的形参类型
  •     auto不能定义为类的非静态成员变量
  •     auto不能直接用来声明数组
  •     auto不能作为实例化的模板参数

auto的优缺点:

auto看起来简化了容器的迭代,是建立在非常熟悉容器结构的情况下。用auto接收一个函数的返回值,但不知道auto的类型,就不好进行遍历,比如,map有一first和second,如果不清楚map的数据结构,就不好进行输出。

auto加for很方便进行容器的遍历。但可读性变差,提高了维护成本,不懂C++语法的人,还要进行学习。

typeid操作符

typeid的作用是在动态运行时获取变量的类型名称,使用typeid(变量).name() ,输出变量的类型名称。比如,

int a = 10;

cout << typeid(a).name() << endl; //int
cout << typeid(1.1f).name() << endl; //float

//对于存在继承关系的类
class Base1 {}; 
class Derive1:public Base1 {}; 
Derive1 d1; 
Base1& b1 = d1; //b1是Deriver1的一个引用
cout << typeid(b1).name() << endl; // 输出"class Base1",因为Derive1和Base1之间没有多态性 

class Base2 {  
     virtual void fun( void ) {} 
}; 
class Derive2:public Base2 { }; 
Derive2 d2; 
Base2& b2 = d2; //b2是Derive2的一个引用
cout << typeid(b2).name() << endl; // 输出"class Derive2",因为Derive1和Base1之间有了多态性

注意:对非引用类型,typeid是在编译时期识别的,只有引用类型才会在运行时识别。

基于范围的for循环

作用:可以用来编历,修改数组,容器等,语法简单。可以和auto搭配使用。

缺点:违背传统C用法,带来可读性上的误区

用法:

//数组
int array = {1,2,3,4};
for(auto e : array) //赋值,将array中的元素依次取出来,赋值给e,e的改变不影响数组
{
    cout << e << " ";
}

//更改数组元素:偶数乘2,这时候要使用&
int array[] = {1,2,3,4};
for(auto& e : array)  //e的改变影响数组
{
    if(e % 2 == 0)
        e = e*2;
}

//容器:vector
vector<int> v{1,2,3,4}; //C++新的初始化的方式
for(auto i : v)
    cout << i <<" ";
cout << endl;


 

decltype

decltype 关键字是为了解决 auto 关键字只能对变量进行类型推导的缺陷而出现的。decltype可以对表达式的类型进行推导。

语法:decltype(表达式)

作用:用来获取表达式的类型,用此类型可以定义一个新的变量。

auto x = 10; //int
decltype(x) y; //int

auto a = 1;
auto b = 2;
decltype(a+b) c; // int c

3、初始化列表

未完待续!

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值