第二章 语言可用性的强化——常量

2.1 常量

nullptr

目的是为了代替NULL。传统C++会把NULL、0视为一种东西,这取决于编译器如何定义NULL。有些编译器会定义为((void)* 0),有些会直接定义为0。

C++不允许直接将void 隐式转换到其他类型。如果编译器尝试把NULL定义为((void) 0),如下代码:

char *ch = NULL;

由于C++没有 void * 的隐式转换,只好将NULL定义为0。表面上是解决了当前问题,但是这样做会产生重载混乱的新问题,如下代码:

void foo(char*);
void foo(int);
...
foo(NULL);  //这个函数会调用 foo(int),不符合直觉,很麻烦

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

所以,作为新时代的C++程序员,请养成使用nullptr的习惯。

constexpr

C++中数组的长度必须是一个常量表达式,你可以以前通过如下代码也可以定义一个数组:

const int len = 10;
int arr[len] = { 0 };

上面的代码可能在大部分编译器上可以跑,但是其实在C++中这是非法的。如果用古老一点的编译器,是会报错的,但是现在的编译器大部分都做了优化,其实这一点非常的不好。

C++11引入了 constexpr关键字,让用户显示的声明函数或对象构造函数在编译期会成为常量表达式。而且,constexpr可以修饰递归,如下代码:

constexpr int fibonacci(const int n)
{
    return n == 1 || n == 2 ? 1 : fibonacci(n - 1) + fibonacci(n - 2); //斐波那契数列
}

int arr[fibonacci(4)] = { 0 };  //声明了一个有3个int元素的数组,每一个元素都是0

C++11引入的constexpr关键字只能修饰简单的函数,就是函数实现只能由 return 一行代码。从C++14开始,constexpr函数可以在内部使用局部变量、循环和分支等简单语句,如下代码:

constexpr int fibonacci(const int n)
{
    if (n == 1)
    {
        return 1;
    }

    if (n == 2)
    {
        return 1;
    }

    return fibonacci(n - 1) + fibonacci(n - 2);
}

和上面的那段代码功能一样,逻辑也是一样的,但是在C++11中是跑不了的。

注意事项

​1.constexpr 修饰符是将编译期运算的结果变成常量表达式,也就是说 constexpr 修饰的对象也要是一个确定不变的值,最起码需要是 const 修饰的值。如下代码:

int a = 1, b = 2;
const int c = 1, d = 2;
constexpr int value1 = a + b;  //错误,a 和 b 是变量,无法在编译期计算出常量值
constexpr int value2 = c + d;  //可以,c 和 d 是 const 常量,可以在编译期确定其值
constexpr int value3 = 1 + 2;  //更可以了

​2.如果是修饰函数,那么返回值一定不能是void ,也就是说一定要有返回值.

​3.C++11时期的constexpr有诸多限制,函数体通常只有一句 return 语句,函数体内既不能声明变量,也不能使用for语句之类的常规控制流语句。

​4.对于自定义类型(自定义类和自定义结构体),不能直接用constexpr修饰。正确的做法应该是在该类型的内部添加一个常量构造函数。如下代码:

struct myType
{
    constexpr myType(string name, int age):m_name(name), m_age(age) {};  //常量构造函数
    string m_name;
    int m_age;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值