这是C++11新特性介绍的第一部分,比较简单易懂,但是也有一些有趣的地方。
  不想看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<<' '<<long_large<<' '<<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)<<' '<<(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<<' '<<limit<<' '<<p4<<' '<<size<<' '<<nsize<<' '<<p6<<' '<<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())<<' '<<noexcept(no_except2())<<endl;
  这种用法表示no_except2和no_except的异常说明保持一致。
  初始化
  列表初始化
  C++11新标准中为很多类型增加了列表初始化的功能。
  可以用列表初始化一个简单变量。
  int single_int1 = 0;
  int single_int2 = {0};
  cout<<"test list initialization: "<<single_int1<<' '<<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: "<<v1[1]<<' '<<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: "<<m1["d"]<<' '<<*s1.find("b")<<endl;