C++ 11新特性

1.新的数据类型long long超长整型,当然还包括它的无符号类型unsigned long long 

2.列表初始化,允许使用花括号来初始化变量

int a{10};

std::vector<int> vec{1,2,3};

在用列表初始化的时候如果遇到精度丢失的情况会报错:

int a{1.55};//编译的时候会报错

3.新增constexpr关键字

constexpr用于定义一个常量表达式,比如我们我们在定义一个变量的时候,不确定赋给变量的值是否为一个常量表达式,就可以用constexpr来代替const来进行声明,用constexpr声明变量后编译器就会自动帮我们检验它的值是否为一个常量表达式

用constexpr声明的变量也是一个常量

还可以使用constexpr来修饰函数的返回值,这样的函数必须确保足够简单能够在编译阶段就能得到函数的返回值。

constexpr函数必须确保函数的返回类型和所有形参类型都是字面值类型,并且函数体中有且只有一条return语句。

用constexpr定义变量的时候只针对内置的普通算数数据类型,引用和指针。比如string,其他库中定义的类,或者自己写的类都不能定义为constexpr类型。

3.使用using来定义类型的别名

和t以前的ypedef的作用一致:

using INT = int; //等价于typedef int INT;

4.新增auto类型说明符

类似C#中的var,在定义变量的时候不同指定变量的类型,让编译器根据赋给变量的值来自行推断变量的类型:

auto x = 3.15;

5.新增decltype用于返回操作数的数据类型:

int x = 10;

decltype(x) y = 20;//等价于int y = 20;

如果decltype后面跟的是双层的括号则它返回的是引用类型:

decltype((x)) c;//编译错误,因为decltype((x))返回的类型是int&,引用类型必须初始化

6.运行在类中定义成员的时候赋值上初始值

struct Person
{
    int Age = 10;
    std::string Name = "maycpou";
    std::string Sex{"male"};
};
 
7.新增范围for语句用于遍历:
std::vector vec{1,2,3,4,5,6};
for(int i :vec){
  std::cout<<i<<std::endl;
}
如果想要使用范围for改变容器中元素的值,则必须声明引用来进行操作:
std::vector vec{1,2,3,4,5,6};
for(int &i :vec){
  i=i+1;
}
范围for循环体中不能包含改变起遍历的序列长度的代码。
 
8.新增cbegin()和cend()迭代器,相比较于begin()和end()迭代器,他们返回的时const_iterator类型的迭代器
也就是不能使用cbegin()或者cend迭代器修改容器中元素的值
 
9.新增全局的begin()和end函数,而不是作为容器的成员函数使用,比如就可以使用这个新政的begin()和end()来获取数组的头尾的迭代器:
char c[]="hello";
    auto itBegin = std::begin(c);
    auto itEnd = std::end(c);
 
10.新增使用initializer_list类型为函数传入可变参数,头文件#include <initializer_list>
int test2(int x ,std::initializer_list<std::string> list){//允许在initializer_list类型的参数前面还有其他类型的参数
    for(auto str:list){//initializer_list和vector容器类似也可以使用加强for来进行遍历
        cout<<str<<endl;
    }
}
int main(int argc,char *argv[]){
    test2(10,{"tttttttttt","aaaaaaaaa"});//传入参数的时候initializer_list中的参数需要用花括号{}括起来
}
 
11.新标准规定函数的声明可以使用尾置返回类型:
如:原函数:
int test(int x){
  return x;
}
改为尾置返回类型:
auto test(int x)->int{//->int表示函数的返回类型是int
  return x;
}
 
12.新增使用=default来为类添加默认的构造函数,可以在类的内部也可以在类的外部:
在类的内部使用:
struct Person
{
    Person()=default;
    Person(string name);
    string Name="maycpou";
    string getName();  
};
string Person::getName(){
    return this->Name;
}
在类的外部使用:
struct Person
{
    Person();
    Person(string name);
    string Name="maycpou";
    string getName();  
};
string Person::getName(){
    return this->Name;
}
Person::Person()=default;
Person::Person(string name){
    this->Name = name;
}
 
13.新增一种构造函数的写法:委托构造函数。将类的一个构造函数委托给类的另一个构造函数进行初始化:
struct Person{
  string Name;
  int Age;
  bool Sex;
  Person(string name,int age,bool sex):Name(name),Age(age),Sex(sex){}//定义一个三个参数的构造函数
  Person(string name):Person(name,0,false){cout<<"test"<<endl;}//定义一个参数的构造函数,它委托给了上面定义的三个参数的构造函数进行构造,Name使用传入的参数进行构造,Age的值使用0,Sex的值使用false。先执行三个参数的构造函数,然后再回来执行自己函数体中的代码cout<<"test"<<endl;
}
 
11.新增容器array。新增的array容器是用来替换原来使用的数组的。
(1)array声明过后它的长度就是固定的不能新增或者删除成员
 std::array<int,6> arr{1,2,3,4,5,6};//声明的时候必须指定长度
    for(auto i:arr){
        cout<<i<<endl;
    }
(2)array相比于传统的数组是一种更加安全更容易使用的数组。它增加了范围检查,并且可以使用一些内置的成员函数。如使用at下标访问,swap交换两个长度和类型都相同的数组,“=”号赋值等操作。与其他容器的swap不同,array容器的swap会真正交换两个容器的元素。
 
12.新增容器forward_list,与list区别在于它是一种单向链表,而list是双向链表。也就是说它的迭代器直接++但是不支持---。forward_list也不支持size来获取容器的大小,它的删除元素添加元素等操作也和普通的容器有很大的差别,如果要使用的话首先去看下它的使用方式。
 
13.新增三个容器的成员函数:emplace、emplace_front、emplace_back。这三个函数的作用和insert、push_front、push_back一致,分别是向容器的指定位置插入元素、向容器头部插入元素、向容器尾部插入元素。
insert、push_front和push_back在插入元素时是将传入的对象拷贝一个副本,将副本插入到容器中。
emplace、emplace_back和emplace_front支持直接传入元素的构造函数的参数,然后系统会根据传入的参数来构造一个该类型的元素对象,将该对象插入到容器中。
struct Person{
  string Name;
  int Age;
  Person(string name,int age){
    this->Name = name;
    this->Age = age;
  }
}
std::vector<Person> personVec;
personVec.emplace_back("Tom",14);
 
14.新增map和set的无序容器版本:unordered_map(无序不重复key的map),unordered_multimap(无序允许重复key的map),unordered_set(无序不重复的set),unordered_multiset(无序允许重复的set)。
由于无序,它们的存储规则是hash桶的方式。由于平时这几个容器使用较少,需要了解的时候再去查询。这里不做详细介绍
原文地址:https://www.cnblogs.com/maycpou/p/14481506.html