1、constexpr 和常量表达式
常量表达式是指值不会改变并且在编译过程就能得到计算结果的表达式。显然,字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式。
例子:(1)const int max_files=20; //max_files是常量表达式
(2)const int limit=max_files+1; //limit是一个常量表达式
(3)int staff_size=27; //staff_size不是常量表达式 原因:尽管staff_size的初始值是个字面值常量,但由于他的数据类型只是一个普通的int而非const int,所以他不属于常量表达式。
(4)const int sz=get_size(); //sz不是常量表达式 原因:尽管sz本身是一个常量,但是他的具体值直到运行时才能获取到,所以也不是常量表达式。
2、声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化:
例子: constexpr int mf=20;//20是常量表达式
constexpr int limit=mf+1;//mf+1是常量表达式
注意:(1)到目前为止我们接触到的数据类型中,算术类型、引用和指针都属于字面值类型。自定义类Sale_item、IO库、string类型则不属于字面值类型,也不能定义成constexpr。
(2)一个constexpr指针的初始值必须是nullptr或者0。
3、类型别名
定义类型别名的方法:(1)传统方法使用关键字typedef 例子:typedef double wages;
(2)别名声明的方法:例子:using SI=Sale_item;//SI是Sale_item的同义词。
4、类型说明符
(1)auto 类型说明符:当我们不知道变量表达式的类型时,可以使用auto让编译器为我们决定表达式的类型。
例子 : auto a = b+c; //编译器会为我们判别类型
auto a = 0, b = 3.14; //错误,auto语句中的类型必须一致。
(2) auto会自动忽略掉顶层const,而底层const会被保留
(3) auto定义的变量必须有初始值
例子;判断下列定义推断出的类型是什么?
const int i=42;
auto j=i; const auto &k=i; auto *p=&i;
const auto j2=i,&k2=i;
解析:
第一个auto j 类型为int
第二个auto &k 类型为const int &
第三个auto *p类型为const int *
第四个auto j2类型为const int
第五个auto &k2 类型为const int&
5、decltype类型指示符:希望从表达式的类型推断出想要定义的变量的类型,该操作返回操作数的类型。
例子1:decltype(f()) sum = s; //sum的类型就是f的返回类型
例子2:
const int ci=0,&cj=ci;
decltype (ci) x=0; //x的类型是const int
decltype (cj)y=x; //y的类型是const int&,y绑定到变量x
decltype(cj)z; //错误:z是一个引用,必须要进行初始化
6、下面代码,请指出每一个变量的类型以及程序结束时他们各自的值。
int a=3,b=4;
decltype(a) c=a;
decltype((b)) d=a;
++c;
++d;
解析:考察的知识点:decltype(())双层括号表示引用(注意引用必须初始化)
a是int类型 4
b是int类型 4
c是int类型 4
d是int &类型 4
7、赋值是会产生引用的一类典型表达式,引用的类型就是左值的类型。也就是说,如果i是int,则表达式i=x的类型是int&。根据这一特点,请指出下面的代码中每一个变量的类型和值。
int a=3,b=4;
decltype(a) c=a;
decltype(a=b) d=a;
解析:知识点:赋值的表达式语句本身是一种引用:
a int 3;
b int 4;
c int 3;
d int & 3;
8、说明由decltype指定类型和由auto指定类型的区别。
主要的区别有两点:
1:如果使用引用类型,auto会识别为其所指对象的类型,decltype则会识别为引用的类型。
2:decltype(())双括号的差别。对于decltype所用的表达式来说,变量名如果加上了一对括号,则得到的类型和不加括号时会有不同。如果decltype使用的是一个不加括号的变量,则得到的结果就是该变量的类型;如果给变量加上一层或者多层括号,编译器就会将其作为一个表达式。变量是一种可以作为赋值语句左值的特殊表达式,所以这样的decltype就会得到引用类型。
例子://decltype加上了括号的变量,结果就是引用
decltype((i)) d; //错误:d是int&,必须初始化
decltype(i) e; //正确:e是一个(未初始化的)int
切记:decltype((variable))(注意是双层括号)的结果永远是引用。
例子:编译下面的例子并运行其结果。
struct Foo{/*此处为空*/} //注意:没有分号
int main()
{
return 0;
}
解析:在没有分号时出现报错:
1>------ 已启动生成: 项目: test2, 配置: Debug Win32 ------
1>test2.cpp
1>e:\cpp\test2\test2.cpp(3): error C2628: “Foo”后面接“int”是非法的(是否忘记了“;”?)
1>e:\cpp\test2\test2.cpp(4): error C3874: “main”的返回类型应为“int”而非“Foo”
1>e:\cpp\test2\test2.cpp(5): error C2440: “return”: 无法从“int”转换为“Foo”
1>e:\cpp\test2\test2.cpp(5): note: 无构造函数可以接受源类型,或构造函数重载决策不明确
1>已完成生成项目“test2.vcxproj”的操作 - 失败。