C++11新增语法(糖)
Posted OshynSong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++11新增语法(糖)相关的知识,希望对你有一定的参考价值。
新增类型
long long
C++11标准中新加入了long long类型属性,占用空间不小于long类型。
long large = LONG_MAX;
long long long_large = LLONG_MAX;
long long long_long_large = 1LL << 63;
cout<<"test long long:"<<large<<'\\t'<<long_large<<'\\t'<<long_long_large<<endl;
测试结果显示long long与long类型均为64bit。
nullptr字面量
新增这个关键字用来初始化一个空指针,可以用来转换为其他任何类型的指针,这个关键字用来替代以前的字面值0
和NULL
两种初始化空指针的方式。
类型相关
auto类型推断
auto关键字,可以让编译器帮我们分析表达式的类型,类似模版形参推断。
需要注意的是:
- 使用auto定义的变量必须有初始值,不然无法进行类型推断
- 在同一条语句中使用auto定义的变量,其基础类型必须一致
double val1 = 1.1, val2 = 2.2;
auto sum = val1 + val2;
auto val3 = 0.3, *p = &val3;
double val6 = 1.6, &rval6 = val6;
auto aval6 = rval6;
aval6 = 6.0; // aval6 is not a reference.
- 顶层const,指的是当前的数据类型本身是常量,如double,int或者相关的指针本身是常量
- 底层const,指的是如指针、引用等复合类型,其所指向的数据类型是常量
auto在进行类型推断时,一般会忽略顶层const(top-level const),而保留底层const(low-level const)。如果想要保留顶层const,则必须显式的在auto前添加const指示符。
const int ci = 1, &cr = ci;
auto b = ci; //b是一个整数,忽略顶层const
auto c = cr; //c是int类型,cr是ci的别名,具有的顶层const忽略了
auto d = &ci; //d是一个指向整形常量的指针
auto &e = ci; //e是一个绑定到ci整形常量的引用
const auto &f = 12; //f是一个整形常量引用,绑定到常量字母量,auto &g = 12是错误的
decltype声明类型
decltype(expr)可以获得expr表达式对应的类型,并且不会对expr具体求值。
int d()
cout<<"This function shouldn't be called."<<endl;
return 17;
decltype(d()) dval17 = 15.2;
上述例子不会调用函数,而只会使用返回类型声明变量。
处理const时,与auto不同:
- 如果decltype中的表达式是一个变量,那么返回该变量的类型(包括顶层const和引用在内),如果变量本身是引用就返回引用类型,否则本身不是引用时,加上括号之后结果永远是引用。
- 如果decltype中的表达式不是变量,则返回该表达式结果对应的类型。
const int ci = 0, &cj = ci;
decltype(ci) x = 0; //x 类型是 const int,保留了顶层const
decltype(cj) y = x; //y 的类型是 const int &,此处是唯一的引用不是与所引用的变量的同义词出现的地方。
int i = 42, *p = &i, &r = i;
decltype(r + 0) b; //b 是一个int类型未初始化的变量,因为r+0表达式不是引用类型
decltype(r) c; //错误,c是int & 类型,必须初始化
decltype(*p) d; //错误,d是int & 类型,必须初始化,解引用运算符返回的类型是引用类型
decltype((i)) e; //错误,e是int & 类型,必须初始化,加上括号后的变量是一个表达式,编译器理解为一个引用
用途:
使用 decltype 简化函数返回类型
如果我们已经知道某个函数会返回什么对象,然而这个对象又是一个类型复杂不好写的对象,那么decltype就可以派上用场了。
int odd[] = 1, 3, 5, 7, 9;
int even[] = 0, 2, 4, 6, 8;
decltype(odd) *get_odd_or_even(int i)
return (i % 2) ? &odd : &even;
auto val26 = get_odd_or_even(1);
cout<<"test decltype to simplify func return type:\\n";
for(auto p = begin(*val26); p != end(*val26); p++)
cout<<p<<' '<<*p<<'\\t';
cout<<endl;
类型别名using
传统方法可以使用typedef定义类型别名,新增了using用法进行别名声明:
using array2d = vector<vector<int>>;
常量表达式constexpr
新增constexpr用于声明常量表达式,编译器会验证此变量的值是否是一个常量表达式。
常量表达式是指值不会改变,而且编译过程就能得到计算结果的表达式。字面值属于一种常量表达式,另一种就是使用const关键字声明的对象(需要用常量表达式进行初始化)。
const int a = 100;
const int b = a + 1;
//以下不是常量表达式
int c = 123; //非const限定
const int d = get_size(); //const限定d不能修改,但编译期间不能计算得到d的值
字面值包括基本数据类型、指针、引用,但指针和引用取决于初始化的值。指针必须初始化为nullptr或者是指向const对象,引用必须是绑定到const对象。函数内部的非静态变量不能使用constexpr,因为其地址不固定,静态类型可以使用constexpr指针和引用。
constexpr指针仅对指针有效是一个常量指针,等价于顶层const,与指针所指对象无关:
// a const pointer point to an int,等价于int *const p = nullptr。p可以常量也可以指向非常量
constexpr int *p = nullptr;
// pp是一个指向const int类型的const指针,等价于const int *const pp = nullptr;
constexpr const int *pp = nullptr;
新增允许定义特殊的constexpr限定的函数,可以用这种函数初始化constexpr表达式。这种函数足以简单,使得编译期间可以计算其结果。
constexpr函数是能用于常量表达式的函数,它遵循以下几条约定:
a.返回类型是字面值类型
b.形参类型是字面值类型
c.函数体中必须有且仅有一条return语句
constexpr int sz() return 42;
constexpr int new_sz(int cnt) return sz() * cnt;
constexpr int size = sz();
constexpr int nsize = new_sz(mf);
一般如果认定变量为常量表达式,就声明为constexpr类型
语法增强
noexcept
noexcept可以用作异常指示符,用于指示一个函数是否会抛出异常。编译器并不检查使用了noexcept的函数是否真的不抛出异常,在运行时,如果一个使用noexcept承诺不抛出异常的函数实际抛出了异常,那么程序会直接终止。
void no_except() noexcept
throw 1;
// the following call will cause terminate
//no_except();
noexcept还可以带参数,noexcept(true)表示不会抛出异常,noexcept(false)表示可能抛出异常。
同时noexcept还可以用作运算符,接受一个函数调用,返回一个bool值表示是否会抛出异常。noexcept运算符并不会对其实参进行求值。
将noexcept运算符,结合带参数的noexcept指示符,可以得到如下常用法:
void no_except2() noexcept(noexcept(no_except()))
cout<<"test noexcept: "<<noexcept(no_except())<<'\\t'<<noexcept(no_except2())<<endl;
这种用法表示no_except2
和no_except
的异常说明保持一致。
列表初始化
可以用列表快速初始化一个容器:
// vector/list list initialization
vector<string> v1 = "ab", "cd", "ef";
list<string> l2"gh", "ij", "kl";
//vector<string> v3("mn", "op", "qr"); // wrong initialization format
cout<<"test vector/list list initialization:\\n"<<v1[1]<<'\\t'<<l2.front()<<endl;
// map/set list initialization
map<string, string> m1 =
"a", "A",
"b", "B",
"c", "C"
;
m1.insert("d", "D");
set<string> s1 = "a", "b", "c";
可以在使用new动态分配内存时使用列表初始化。
vector<int> *pv = new vector<int>0, 1, 2, 3, 4;
int *pi = new int[5]0, 1, 2, 3, 4;
cout<<"test new alloator using list initialization:\\n"<<(*pv)[2]<<'\\t'<<pi[2]<<endl;
可以在传入参数/函数返回值时使用列表初始化。
vector<string> error_msg(int typ)
switch(typ)
case 1:
return "type1", "msg1";
case 2:
return "type2", "msg2";
default:
return ;
pair<string, string> get_pair(int typ)
if(typ == 1) return "key", "value";
return pair<string, string>("default key", "default value");
以上是关于C++11新增语法(糖)的主要内容,如果未能解决你的问题,请参考以下文章