auto
  C++11引入的auto关键字实现类型退到,通过这个关键字不仅能方便地获取复杂的类型,而且还能简化书写,提高编码效率。
  auto x = 5;   //OK
  auto pi = new auto(1);  //OK
  const auto *v = &x, u = 6;  //OK
  auto int r;   //error:auto不在表示存储类型指示符,这也是新更改的特性
  auto str;     //error:无法推导出str类型
  Note:v与u的推导需要注意两个小地方
  1)虽然经过前面const auto *v = &x 的推导,auto的类型可以确定为int,但是u仍然必须要写后面的“=6”,否则编译不通过。
  2)U的初始化不能使编译器推导产生二义性。ep:u = 6改为 u = 6.0, 编译器会报错。
  auto并不代表实际的类型声明,仅仅是一个类型声明的“占位符”。
  使用auto声明的变量必须马上初始化,让编译器推导出它的实际类型,并在编译时将auto占位符替换为真正的类型。
  在C++11之前,auto 表示“具有自动存储期的局部变量”,不过其实它在这方面的作用不大,auto int i = 1; 对这个我们再熟悉不过了。不写auto也是一样的效果是为了跟static int j = 1;区分开来而已。
  auto推导可以和指针,引用结合起来使用,还可以带上const,volatile限定符。
  int x = 1;
  const auto e =x;     //const int
  auto f = e;         //int
  const auto& g = x;   //const int&
  auto& h= g;    //const int&
  从上面的例子不难看出:
  1)当不声明为指针和引用时,auto的推导结果和初始化表达式抛弃引用和CV限定符后类型一致。
  2)当声明为指针或者引用时,auto的推导结果将保持初始化表达式的cv属性。
  decltype
  decltype关键字,用来在编译时推导出一个表达式的类型。语法格式:
  decltype(exp)
  int x = 0;
  decltype(x) y = 1;   // y->int
  const int& i = x;    //i->const int &
  decltype(i) j = y;    //j->const int &
  const decltype(y) * p =&z;  // p->const int *
  decltype(x) * pi = &x;   //*pi->int
  decltype(pi)* pii = &pi   //*pii->int *
  从上面的例子不难看出decltype的推导规则:
  1)exp是标示符,雷访问表达式,decltype(exp)和exp类型一致
  2)exp是函数调用,decltype(exp)和返回值的类型一致
  3)若exp是一个左值,则decltype(exp)是exp类型的左值引用,否则和exp类型一致。
  decltype与引用
  int i = 42;
  int *p = &i:
  decltype(*p) c;//error:c是int &必须初始化
  所以如果表达式是解引用的操作,则decltype得到引用类型。解引用可以得到指针所指的对象,而且还能给这个对象赋值。
  decltype与auto还有一个重要的区别:decltype与表达式的形势密切相关。对于decltype所用的表达式来说,如果变量名加上了一对括号,则得到的类型与不加括号是不一样的。也是说decltype使用一个不加括号的变量,则得到的结果是该变量的类型。而加上一层或者多层括号的是作为一个特殊的左值表达式。得到的是引用类型。
  decltype(i) = e;  //OK
  decltype((i)) = e;  //error:e为引用类型必须初始化
  explicite
  explicit使用注意事项:
  *explicit 关键字只能用于类内部的构造函数声明上。
  *explicit 关键字作用于单个参数的构造函数。
  在C++中,explicit关键字用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换。
  explicit关键字只能用于类内部的构造函数声明上。在类的定义体外部所做的定义上不能再重复它。
  如果一个类或结构存在多个构造函数时,explicit 修饰的那个构造函数是默认的
  当构造函数被声明为explicit时,编译器将不使用它作为转换操作符。
  explicit 关键字作用于单个参数的构造函数。
  通常,除非有明显的理由想要定义隐式转换,否则,单形参构造函数应该为explicit。
  inline
  1) inline表示内联,即在函数调用出将函数内联地展开。
  2) inline既可以出现在类定义内部,也可以出现在外部。当在外部出现时必须定义在类定义的头文件中,因为调用函数时需要看到函数是什么样子。
  3)inline修饰的函数是在编译时期。
  constexptr
  这个constexptr函数指能用于常量表达式的函数。定义为constexptr的函数的方法与其它函数类似。不过要遵循:函数的返回类型及所有形参的类型都得是字面值类型,而且函数体中必须有且只有一条return语句:
  constexptr int new_sa() {return 42;}
  constexptr int foo = new_sa();//OK
  我们把new_sz定义成无参数的constexpr函数。因为编译器能在程序编译时验证new_sz函数的返回的是常量表达式,所有可以用new_sz函数初始化constexpr类型的变量foo。
  执行该初始化任务时,编译器把对constexpr函数的调用替换成其结果值。为了能在编译过程中随时展开,constexpr函数被隐式的定义为内联函数。
  constexpr函数体内也可以包含其他语句,只要这些语句在运行时不执行任何操作行。例如,constexpr函数中可以有空语句、类型别名以及using声明。
  我们允许constexpr函数的返回值并非一个常量:
  //如果arg是常量表达式,则scale(arg)也是常量表达式
  constexpr size_t scale(size_t cnt) {return new_sz()*cnt;}
  当scale的实参是常量表达式时,它的返回值也是常量表达式:反之则不然:
  int arr[scale(2)]; //正确:scale(2)是常量表达式
  int i=2; //i不是常量表达式
  int a2[scale(i)]; //错误:scale(i)不是常量表达式
  如上例所示,当我们给scale函数传入一个形如字面值2的常量表达式时,它的返回类型也是常量表达式。此时,编译器用相应的结果值替换对scale函数的调用。
  如果我们用一个非常量表达式调用scale函数,比如int类型的对象i,则返回值是一个非常量表达式。当把scale函数用在需要常量表达式的上下文中时,由编译器负责检查函数的结果是否符合要求。如果结果恰好不是常量表达式,编译器将发出错误信息。
  constexpr函数不一定返回常量表达式
  我也有点云里雾里的。大家看着理解吧。
  把内联函数和constexpr函数放在头文件内
  和其他函数不一样,内联函数和constexpr函数可以再程序中多次定义。毕竟,编译器要想展开函数仅有函数声明是不够的,还需要函数的定义。不过,对于某个给定的内联函数或者constexpr函数来说,它的多个定义必须定义一致。基于这个原因,内联函数和constexpr函数通常定义在头文件中。
  friend
  1) 类的friend函数可以访问类的private和protected成员。
  2) friend关系不能继承,基类的友元对子类的成员没有特殊访问权限,如果基类被授予友元关系,则只有基类具有特殊访问权限,其派生类不能访问授予友元关系的类。
  3) 派生类的friend函数可以访问派生类的一切变量,包括从基类继承下来的protected域中的变量,但对父类来说它不是friend。也是说friend和类本身的访问权是。
  4) friend关键字只能出现在类定义内部,不可出现在外部。
  #include
  #include
  class Point
  {
  public:
  Point(double xx, double yy) { x=xx; y=yy; }
  void Getxy();
  friend double Distance(Point &a, Point &b);
  private:
  double x, y;
  };
  double Distance(Point &a, Point &b)
  {
  double dx = a.x - b.x;
  double dy = a.y - b.y;
  return sqrt(dx*dx+dy*dy);
  }
  static
  在C++中此关键字用途更多。
  1) static类成员属于整个类,不属于某个类对象。
  2) static成员遵循正常的公有/私有访问规则。
  3) 对于public static成员可以通过类名或对象名访问,对于private static成员则不可,须按照正常private成员访问规则进行访问。
  (4) static成员函数可以访问static成员函数和变量,不可访问非static成员和函数,因为static成员是类的,而非static是对象的,类的产生先于对象,怎么能在对象为产生之间调用它的数据呢。
  5) 非static成员函数既可以访问static成员又可以访问非static成员。
  6) 可以通过类名直接调用public static成员,或者通过对象名、引用或指针间接调用。注意此处指的是public static成员,不是private。
  7) static成员函数没有this指针,因为this指向的是对象。
  8) static成员函数不能声明为const或虚函数,因为此二者都是针对对象而言,此外static函数实际上是”加上了访问控制的全局函数”,全局函数当然没有虚函数。但是static变量可以声明为const。