C++11新特性之新类型与初始化
2016-06-22 00:00
591 查看
这是C++11新特性介绍的第一部分,比较简单易懂,但是也有一些有趣的地方。
不想看toy code的读者可以直接拉到文章最后看这部分的总结。
在我的机器上实测,long long类型和long类型同样使用64bit空间。
最终测试结果,nullptr和NULL和0是一样的。
值得注意的是,constexpr指针可以指向非常量变量,只要此变量定义于函数之外,因为这样的变量的指针(地址)是可以在编译期确定的。
另外,下面的constexpr指针与const指针的含义是完全不同的:
第一个指针表示一个常量指针,即指针的值是常量;而第二个指针表示一个指向const int的指针,即指针指向的值是常量。
constexpr还可以用于函数,constexpr函数是指能用于常量表达式的函数,它遵循以下几条约定:
noexcept还可以带参数,noexcept(true)表示不会抛出异常,noexcept(false)表示可能抛出异常。
同时noexcept还可以用作运算符,接受一个函数调用,返回一个bool值表示是否会抛出异常。noexcept运算符并不会对其实参进行求值。
将noexcept运算符,结合带参数的noexcept指示符,可以得到如下常用法:
这种用法表示no_except2和no_except的异常说明保持一致。
可以用列表初始化一个简单变量。
可以用列表初始化一个容器(vector,list,map,set…)。
可以在使用new动态分配内存时使用列表初始化。
可以在传入参数/函数返回值时使用列表初始化。
nullptr字面量用于表示空指针。
constexpr用于表示常量表达式。
noexcept可以用于指示一个函数是否会抛出异常,同时可以用作运算符判定一个函数是否承诺不抛出异常。
新增基础类型、容器类型、new分配内存时的列表初始化。构建临时变量时也可以直接使用列表初始化。
可以直接对类内成员进行初始化/列表初始化。
完整代码详见new_type_and_keywords.cpp 和 initialize.cpp。
不想看toy code的读者可以直接拉到文章最后看这部分的总结。
新类型
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字面量
C++11标准中专门为空指针增加了nullptr字面量,同时不推荐再使用NULL或者0表示空指针。int *p1 = nullptr; int *p2 = 0; int *p3 = NULL; cout<<"test nullptr: "<<(p1 == p2)<<'\t'<<(p1 == p3)<<endl;
最终测试结果,nullptr和NULL和0是一样的。
constexpr
C++11标准中新增constexpr用于声明常量表达式,编译器会验证此变量的值是否是一个常量表达式。int out_i = 0; // out_i定义于函数外部 ... constexpr int mf = 20; constexpr int limit = mf + 1; constexpr int *p4 = &out_i; // the following would cause a make error // since large is not a constexpr //constexpr int wrong = large + 1; // since &in_j is not a constexpr; //int in_j = 0; //constexpr int *p5 = &in_j;
值得注意的是,constexpr指针可以指向非常量变量,只要此变量定义于函数之外,因为这样的变量的指针(地址)是可以在编译期确定的。
另外,下面的constexpr指针与const指针的含义是完全不同的:
constexpr int *p6 = nullptr; // a const pointer point to an int // p6 = &out_i; // error: p6 is a constexpr const int *p7 = nullptr; // a pointer point to a const int
第一个指针表示一个常量指针,即指针的值是常量;而第二个指针表示一个指向const int的指针,即指针指向的值是常量。
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 int wrong_size = new_sz(out_i); // error: out_i is not a constexpr cout<<"test constexpr: "<<mf<<'\t'<<limit<<'\t'<<p4<<'\t'<<size<<'\t'<<nsize<<'\t'<<p6<<'\t'<<p7<<endl;
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的异常说明保持一致。
初始化
列表初始化
C++11新标准中为很多类型增加了列表初始化的功能。可以用列表初始化一个简单变量。
int single_int1 = 0; int single_int2 = {0}; cout<<"test list initialization:\n"<<single_int1<<'\t'<<single_int2<<endl;
可以用列表初始化一个容器(vector,list,map,set…)。
// 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"}; cout<<"test map/set list initialization:\n"<<m1["d"]<<'\t'<<*s1.find("b")<<endl;
可以在使用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;
可以在传入参数/函数返回值时使用列表初始化。
m1.insert({"d", "D"}); 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"); } vector<string> err_msg1 = error_msg(1); vector<string> err_msg2 = error_msg(2); vector<string> err_msg3 = error_msg(3); cout<<"test return value list initialization:\n"<<err_msg1[1]<<'\t'<<err_msg2[1]<<'\t'<<err_msg3.empty()<<endl; pair<string, string> p1 = get_pair(1); pair<string, string> p2 = get_pair(2); cout<<"test return pair list initialization:\n"<<p1.first<<'\t'<<p2.first<<endl;
类内成员初始化
C++11标准中允许直接对类内成员进行初始化/列表初始化。class InitClass { public: void print_class() { cout<<field1<<'\t'<<field2<<'\t'<<field3<<'\t'<<field4<<endl; } private: int field1 = 1; int field2; double field3 = 1.0; double field4; }; class InitClassMgr { public: vector<InitClass> init_objs = {InitClass()}; }; InitClass test_class; cout<<"test class member initialization:\n"; test_class.print_class(); InitClassMgr mgr; cout<<"test class member of class type initialization:\n"; mgr.init_objs[0].print_class();
总结
long long类型。nullptr字面量用于表示空指针。
constexpr用于表示常量表达式。
noexcept可以用于指示一个函数是否会抛出异常,同时可以用作运算符判定一个函数是否承诺不抛出异常。
新增基础类型、容器类型、new分配内存时的列表初始化。构建临时变量时也可以直接使用列表初始化。
可以直接对类内成员进行初始化/列表初始化。
完整代码详见new_type_and_keywords.cpp 和 initialize.cpp。
相关文章推荐
- [win32][c++]如何覆盖winAPI控件自带的加速键
- 关于c++变长参数列表总结
- C/C++中函数调用规则(约定)__cdecl __stdcall __thiscall __vectorcall __fastcall
- C++ (重载、覆盖、隐藏)
- C语言中,有符号数,无符号数,整数溢出
- Product of Array Except Self
- 数字阶梯求和
- C++对象所占内存的大小
- c语言学习笔记33之void
- Calculation
- Search a 2D Matrix II
- [转载]C语言字节对齐(以32位系统为例)
- 你最需要注意的11条要点for C++
- C++常类型(const)
- C语言中的typedef问题
- C++ 中的单例模式
- C语言链式栈和顺序栈的实现
- C语言数组,顺序表的初始化,添加,删除和打印
- C语言单链表的3种排序算法,插入排序,冒泡排序,选择排序
- 课程表(c语言)