C++笔记 | C++ 11新特性nullptr使用,常数表达式constexpr,类型推导auto和decltype

nullptr 

nullptr 出现的目的是为了替代 NULL。在某种意义上来说,传统 C++ 会把 NULL0 视为同一种东西,这取决于编译器如何定义 NULL,有些编译器会将 NULL 定义为 ((void*)0),有些则会直接将其定义为 0

C++ 不允许直接将 void * 隐式转换到其他类型,但如果 NULL 被定义为 ((void*)0),那么当编译

char*ch=NULL;

时,NULL 只好被定义为 0。而这依然会产生问题,将导致了 C++ 中重载特性会发生混乱,考虑:

voidfoo(char *);

voidfoo(int);

对于这两个函数来说,如果 NULL 又被定义为了 0 那么 foo(NULL); 这个语句将会去调用 foo(int),从而导致代码违反直观。

voidfoo(char *);

voidfoo(int);

对于这两个函数来说,如果 NULL 又被定义为了 0 那么 foo(NULL); 这个语句将会去调用 foo(int),从而导致代码违反直观。

为了解决这个问题,C++11 引入了 nullptr 关键字,专门用来区分空指针、0。nullptr 的类型为 nullptr_t,能够隐式的转换为任何指针或成员指针的类型,也能和他们进行相等或者不等的比较

constexpr

C++ 本身已经具备了常数表达式的概念,比如 1+2, 3*4 这种表达式总是会产生相同的下结果并且没有任何副作用。如果编译器能够在编译时就把这些表达式直接优化并植入到程序运行时,将能增加程序的性能。一个非常显著的例子就是在数组的定义阶段:

#define LEN 10

 

int len_foo() {

    return 5;

}

 

int main() {

    char arr_1[10];

    char arr_2[LEN];

    int len = 5;

   char arr_3[len+5];          // 非法

    const int len_2 = 10;

    char arr_4[len_2+5];        // 合法

    char arr_5[len_foo()+5];  // 非法

 

    return 0;

}

在 C++11 之前,可以在常量表达式中使用的变量必须被声明为 const,在上面代码中,len_2 被定义成了常量,因此 len_2+5 是一个常量表达式,所以能够合法的分配一个数组;

而对于 arr_5 来说,C++98 之前的编译器无法得知 len_foo() 在运行期实际上是返回一个常数,这也就导致了非法的产生。

C++11 提供了 constexpr 让用户显式的声明函数或对象构造函数在编译器会成为常数,这个关键字明确的告诉编译器应该去验证 len_foo 在编译器就应该是一个常数。

类型自动推导auto和decltype

C++中每个变量的类型都需要明确定义,这实际上对我们进行快速编码没有任何帮助,尤其是当我们面对一大堆复杂的模板类型时,必须明确的指出变量的类型才能进行后续的编码,这不仅拖慢我们的开发效率,也让代码变得又臭又长。

可以使用auto和decltype关键字来进行变量的自适应

从前使用迭代器来进行vector的访问需要这么写

For(vector<int>::iterator it =vec.begin();it ! = vec.end();it++)

现在可以这么写

For(auto it = vec.begin();it ! =vec.end();it++)

还可以这么写

Auto i = 5;//i被推导为int

Auto i = new auto(10)//i被推导为int *类型

Auto变量不能用于函数参数,如果想要实现类似的功能,可以使用函数模板

比如int a(autoc,auto d){return 3;}无法通过编译

Auto不能用来推导数组类型,

比如autoaa[3]={1,2,3}

Int cc[3];

Auto aa = cc;//这里妄图使aa成为int *类型,其本质上仍然是数组

Decltype的使用

Decltype的出现能够弥补auto只能对变量进行类型推导

Decltype的使用方法和sizeof的使用方法类似

Decltype(表达式)

比如这么使用 auto a =1;

Auto b = 2;

Decltype(a + b) c;

Decltype可以当做类型使用,直接用来定义变量

 

  对于某些模板函数而言,其返回类型不能确定,在一般情况下我们只能这样写:

Template<class R, class T, class Q>

R add(T a, Q b)

{return a + b;}

但是这样的代码是很“丑陋”的,因为你在使用add函数的时候,需要提前定义返回值的类型,当add里面的内容非常的复杂,返回值的类型是难以确定的

  所以很容易就能想到以下写法:

Decltype(a + b) add(T a,Q b);

但是当程序运行到函数这里,a和b还没有定义,不能完成编译

  为了解决这个问题,C++11引入了一个叫做返回类型后置的机制,写法如下:

Template<class T, class Q>

auto add(T a, Q b) -> decltype(a + b) {

return a + b;

}

  但是C++14开始,函数能够具备返回值推导,因此下面的写法是正确的:

Template<class T, class Q>

auto add(T a, Q b) {

return a + b;

}

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值