C++11初了解

##C++11初认识

###(1)初始化

void test()
{
  vector v1{1, 2, 3, 4, 5, 6 };
  for(int i = 0; i < v1.size(); ++i)
  {
    cout<
结果:1 2 3 4 5 6

###(2)auto关键字
在之前,auto关键字被当做是存储类型的指示符,但是在C++11中
auto完全有了新的含义 ,auto 作为一个新的类型指示符,其声明的变量必须由编译器在编译期间推倒而来
下面的例子

void test_1()                                                                   
{                                                                               
  int a = 10;                                                                   
  auto b = a;                                                                   
  auto c = 'c';                                                                 
  //auto d;                                                                     
  cout << typeid(a).name() << endl;                                             
  cout << typeid(b).name() << endl;                                             
  cout << typeid(c).name() << endl;                                             
}   
结果:i  i  c

我们发现auto在定义变量时必须初始化,需要根据后面的表达式来推断出变量类型,编译期间会将auto自动替换为对应的类型
###auto 的优势
(1)用于复杂类型定义

void test_2()
{
  map m1{{1,2},{3,4},{5,6}};
  //map::iterator it = m1.begin();
  auto it = m1.begin();
  while(it != m1.end())
  {
    cout<second<<" ";
    it++;
  }
  cout<
结果:2 4 6 

(2)避免在类型上声明的错误

void test_3()
{
  const float pi = 3.14f;
  double radis = 3.0;
  auto c = 2 * pi * radis;
  cout<

输出结果

结果:18.84  d

(3)for循环遍历

void test_4()
{
  vector v1{"hello", "world", "!"};
  for(auto item :  v1)
  {
    cout<
结果:hello world !

#####auto 的优点和缺点
优点:简单方便
缺点: 可读性差(定义复杂类型时读者不易于观察到类型)
#####不适合用auto的场景

  1. 不能用来声明数组
  2. 不作为模板参数
  3. 不能定义类的非静态成员变量
  4. 不能作为函数的形参

###(2)decltype
虽然C98中已经有了RTTI(运行时类型识别) 我们上面使用的typeid 和 dynamic_cast
但是都有其不足处,dynamic_cast 只能用在虚函数的继承体系中,typeid只能用来识别出类型,不能定义变量。
decltype定义变量不用初始化

void test_5()
{
  int a = 10;
  decltype (a) b;
  b = 10;
  cout<< a<< " "<
结果:10 10

推倒函数返回值类型

int add(int a, int b)
{
  return a + b;
}

void test_6()
{
  int a = 3, b = 6;
  cout<
结果:i

###(3)lambda表达式
lambda表达式书写格式

  //书写格式
  [capture] (paramenters) mutable ->return-type {statement}
  //[捕捉列表] 可以用来捕捉上下文中变量提供的lambda函数使用
  //(参数列表)
  //mutable 默认情况下lambda函数为一个const函数,若添加上mutable可以取消其常性,该时参数列表不可以为空
  //return-type 返回值
  //{statement}函数

  //参数列表和返回值都是可选部分,没有可以不用写,而捕捉列表和函数体是可以为空的
  //即最简单的lambda表达式为[]{};

捕捉列表的形式有以下几种:

[var] :表示值传递方式捕捉某个人变量var
[=]   :表示以值传递方式捕获所有父作用域中的变量
[&var]:表示以引用传递捕捉所有父作用域中的某个变量
[&]   :表示以引用的方式捕捉父作用域中的所有变量
[this]:值传递方式捕捉当前的this指针
当然上面的几种方式可以混合使用

举例说明

void test_8()                                                                   
{                                                                               
  int a = 3,b = 4;                                                              
  cout<<"a:"<
结果:
a:3b:4
a:4b:3

看上面的形式我们很容易就发现很类似于仿函数,看大牛的博客说,其实仿函数的实现就是用lambda的一种

###(4)默认函数控制
#####(1)显示缺省函数函数
指定默认构造函数
因为我们知道,当我们自己实现了构造函数就不会生成默认的构造函数
但是当使用的default 关键字的时候,就可以指定自己想要的默认构造函数
#####(2)删除函数
想要限制默认函数的生成
在单例模式下,我们要实现防拷贝和防赋值运算符重载,普通的做法是声明为私有,在C++11中就可以简单的实现了

  class A                                                                                                                                                      
  {                                                                                                                                                            
    public:                                                                                                                                                    
      A(int a):_a(a){}                                                                                                                                         
      A(const A & a) = delete;                                                                                                                                 
    private:                                                                                                                                                   
      int _a;                                                                                                                                                  
  };                                                                                                                                                           
                                                                                                                                                               
  void test_9()                                                                                                                                                
  {                                                                                                                                                            
    A a1(25);                                                                                                                                                  
   // A a2(a1);   //这一行会报错,因为上面我们将拷贝构造声明为删除函数,起到了防拷贝的效果                                                                                                                                               
  }      

删除函数还可以起到防止隐士类型转换的作用

  class A                                                                                                                                                      
  {                                                                                                                                                            
    public:                                                                                                                                                    
      A(int a):_a(a){}                                                                                                                                         
      A(char a) = delete;                                                                                                                                      
      A(const A & a) = delete;                                                                                                                                 
                                                                                                                                                               
    private:                                                                                                                                                   
      int _a;                                                                                                                                                  
  };                                                                                                                                                           
                                                                                                                                                               
  void test_9()                                                                                                                                                
  {                                                                                                                                                            
    A a1(25);                                                                                                                                                  
    A a2('a');//这里会报错,因为上面将参数类型为char 的构造函数声明为删除函数,即起到了防止隐士类型转换的作用                                                                                                                                                 
  }          

###(5)final
final修饰一个虚函数时,表明该函数不可以被重写

 class Base                                                                                                                                                   
  {                                                                                                                                                            
    public:                                                                                                                                                    
      virtual void Func()final                                                                                                                                 
      {                                                                                                                                                        
        cout << "Base::Func()" << endl;                                                                                                                        
      }                                                                                                                                                        
  };                                                                                                                                                           
                                                                                                                                                               
  class Derived : public Base                                                                                                                                  
  {                                                                                                                                                            
    public:                                                                                                                                                    
    //  void Func()   // 报错                                                                                                                                        
    //    {                                                                                                                                                      
    //      cout << "Base::Func()" << endl;                                                                                                                      
    //    }                                                                                                                                                      
  };       

final修饰一个类的时候,表明该类不可以被继承

class Base final
 {
     virtual void Func()
     {
         cout << "Base::Func()" << endl;
     }
 }; 
///class Derived : public Base //报错
//{
// public:
//      virtual void Func()
//	{			
//         cout << "Base::Func()" << endl; 
//    } 
//}; 

####(6)override
在子类的虚函数中使用,如果构成隐藏就报错
当子类中不小心重写了父类的非虚函数的时候,如果加上了override 就会报错

                                                                                                                                                               
class Base                                                                                                                                                     
{                                                                                                                                                              
  public:                                                                                                                                                      
    virtual void Func()                                                                                                                                        
    {                                                                                                                                                          
      cout << "Base::Func()" << endl;                                                                                                                          
    }                                                                                                                                                          
    virtual void Func_2()                                                                                                                                      
    {                                                                                                                                                          
      cout << "Base::Func()" << endl;                                                                                                                          
    }                                                                                                                                                          
    void func()                                                                                                                                                
    {                                                                                                                                                          
      //do something                                                                                                                                           
    }                                                                                                                                                          
};                                                                                                                                                             
                                                                                                                                                               
class Derived : public Base                                                                                                                                    
{                                                                                                                                                              
  public:                                                                                                                                                      
    virtual void Func() override                                                                                                                               
    {                                                                                                                                                          
      cout << "Base::Func()" << endl;                                                                                                                          
    }                                                                                                                                                          
    //构成重写,编译器会报错                                                                                                                                                           
   // virtual void Func_2(int a) override                                                                                                                      
   // {                                                                                                                                                        
   //   cout << "Base::Func()" << endl;                                                                                                                        
   // }                                                                                                                                                        
                                                                                                                                                               
   // virtual void func() override                                                                                                                             
   // {                                                                                                                                                        
   //   //do something                                                                                                                                         
   // }                                                                                                                                                        
};             

###移动语义
很多时候当我们将一个返回一个对象时,中间要经过
1、先拷贝一个临时对象
2、再在接受返回值的地方进行一次拷贝
我们发现整个过程中我们进行了两次拷贝,并且中间的那次临时对象的生命周期是极其的短暂
在C++11中提出了移动语义的概念
例如在实现 运算符重载的过程中 operator+()
C++11初了解_第1张图片

C++11初了解_第2张图片

我们看到移动语义就像是将临时变量的构造函数偷走了,一种资源转移的,也就是移动语义的解释
要实现移动语义,必须要借助C++11中的右值引用来完成

String(String&& s)
     : _str(s._str)
     {
          s._str = NULL;
     } 

先来看什么是左值和右值
一般来说说,可以取地址成功的就是左值,剩下的就是右值
C++11中的右值有两层含义
1、纯右值,C98中的概念,用于辨识临时变量和一些与对象没有关联的值
2、将亡值,C++11新增的跟右值引用相关的表达式,这些表达式通常是将要被 移动的对象

String ReturnRValue() 
{ 
    return String("1234"); 
} 
void TestString() 
{
     String&& s = ReturnRValue();
} 

上面的这个式子中我们发现,声明一个名为s 的右值引用,ReturnRValue()函数返回的右值在表达式语句结束 后,其生命周期也就终结,而右值引用的声明,该右值又”重获新生”, 其生命周期就与s的生命周期一样。

注意:
1、无论左值引用还是右值引用,都是引用,所以必须初始化,只是其引用对象的别名
2、通常情况下,右值引用是不能绑定到任何左值
std::move()
函数会强制的将其转换为右值
但是一般不建议随便使用,一般用在将亡值

String s1("hello world");
String s2(move(s1));
String s3(s2); 

上面的代码就构成了s1的右值引用,并且赋值给了s2
这样就是s1将资源转给了s2,s1 资源无效

本人了解的大概就这么多了
完。

你可能感兴趣的:(C,++)