c++基础知识汇总

Posted Relievedz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++基础知识汇总相关的知识,希望对你有一定的参考价值。

目录

1、基础

1.2 注释

1.3 变量

1.4 常量

1.5 关键字

1.6 标识符命名规则

2 数据类型

2.1 整型

2.2 sizeof关键字

2.3 实型(浮点型)

2.4 字符型

2.5 转义字符

2.6 字符串型

2.7 布尔类型 bool

2.8 数据的输入


1、基础

1.2 注释

作用:在代码中加一些说明和解释,方便自己或其他程序员程序员阅读代码

两种格式

  1. 单行注释// 描述信息

    • 通常放在一行代码的上方,或者一条语句的末尾,==对该行代码说明==

  2. 多行注释/* 描述信息 */

    • 通常放在一段代码的上方,==对该段代码做整体说明==

提示:编译器在编译代码时,会忽略注释的内容

1.3 变量

作用:给一段指定的内存空间起名,方便操作这段内存

语法数据类型 变量名 = 初始值;

示例:

#include<iostream>
using namespace std;
​
int main() 
​
    //变量的定义
    //语法:数据类型  变量名 = 初始值
    //变量创建的语法:数据类型 变量名 = 变量初始值
​
    int a = 10;
​
    cout << "a = " << a << endl;
    
    system("pause");
​
    return 0;

注意:C++在创建变量时,必须给变量一个初始值,否则会报错

1.4 常量

作用:用于记录程序中不可更改的数据

C++定义常量两种方式

  1. #define 宏常量: #define 常量名 常量值

    • ==通常在文件上方定义==,表示一个常量

  1. const修饰的变量 const 数据类型 常量名 = 常量值

    • ==通常在变量定义前加关键字const==,修饰该变量为常量,不可修改

示例:

#include<iostream>
using namespace std;

//常量的定义方式
//1. #define 宏常量: 
//2.const**修饰的变量

//1、宏常量
#define Day 7

int main() 

    //Day = 8;  //错误,Day是常量,一旦修改就会报错
    cout << "一周里总共有 " << Day << " 天" << endl;
    
    //2、const修饰变量
    const int month = 12;
    //month = 24; //报错,const修饰的常量也称为变量
    cout << "一年里总共有 " << month << " 个月份" << endl;
    

    system("pause");
    return 0;

1.5 关键字

作用:关键字是C++中预先保留的单词(标识符)

  • 在定义变量或者常量时候,不要用关键字

C++关键字如下:

asmdoifreturntypedef
autodoubleinlineshorttypeid
booldynamic_castintsignedtypename
breakelselongsizeofunion
caseenummutablestaticunsigned
catchexplicitnamespacestatic_castusing
charexportnewstructvirtual
classexternoperatorswitchvoid
constfalseprivatetemplatevolatile
const_castfloatprotectedthiswchar_t
continueforpublicthrowwhile
defaultfriendregistertrue
deletegotoreinterpret_casttry

提示:在给变量或者常量起名称时候,不要用C++得关键字,否则会产生歧义。

1.6 标识符命名规则

作用:C++规定给标识符(变量、常量)命名时,有一套自己的规则

  • 标识符不能是关键字

  • 标识符只能由字母、数字、下划线组成

  • 第一个字符必须为字母或下划线

  • 标识符中字母区分大小写

建议:给标识符命名时,争取做到见名知意的效果,方便自己和他人的阅读

2 数据类型

C++规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存

2.1 整型

作用:整型变量表示的是==整数类型==的数据

C++中能够表示整型的类型有以下几种方式,区别在于所占内存空间不同

数据类型占用空间取值范围
short(短整型)2字节(-2^15 ~ 2^15-1)
int(整型)4字节(-2^31 ~ 2^31-1)
long(长整形)Windows为4字节,Linux为4字节(32位),8字节(64位)(-2^31 ~ 2^31-1)
long long(长长整形)8字节(-2^63 ~ 2^63-1)

#include<iostream>
using namespace std;

int main()
    
    //整形
    //1、短整型(-32768-32767)
    short num1 = 32768;


    //2、整形
    int num2 = 32768;
    
    //3、长整型
    long num3 = 10;

    //4、长长整型
    long long num4 = 10;

    //输出语句
    cout << "num1=" << num1 << endl;
    cout << "num2=" << num2 << endl;
    cout << "num3=" << num3 << endl;
    cout << "num4=" << num4 << endl;

    system("pause");

    return 0;

2.2 sizeof关键字

作用:利用sizeof关键字可以==统计数据类型所占内存大小==

语法: sizeof( 数据类型 / 变量)

示例:

#include<iostream>
using namespace std;

int main() 

    //整型:short (2) int(4) long(4) long long (8)
    //可以利用sizeof求出数据类型占用内存大小
    //语法:sizeof(数据类型/变量)
    
    short num1 = 10;
    cout << "short 类型所占内存空间为: " << sizeof(short) << endl;

    int num2 = 10;
    cout << "int 类型所占内存空间为: " << sizeof(int) << endl;

    long num3 = 10;
    cout << "long 类型所占内存空间为: " << sizeof(long) << endl;

    long long num4 = 10;
    cout << "long long 类型所占内存空间为: " << sizeof(long long) << endl;

    //整型大小比较
    //short < int <= long <= long long

    system("pause");

    return 0;

整型结论:==short < int <= long <= long long==

2.3 实型(浮点型)

作用:用于==表示小数==

浮点型变量分为两种:

  1. 单精度float

  2. 双精度double

两者的区别在于表示的有效数字范围不同。

数据类型占用空间有效数字范围
float4字节7位有效数字
double8字节15~16位有效数字

示例:

int main() 
​
    float f1 = 3.14f;
    double d1 = 3.14;
​
    cout << f1 << endl;
    cout << d1<< endl;
​
    cout << "float  sizeof = " << sizeof(f1) << endl;
    cout << "double sizeof = " << sizeof(d1) << endl;
​
    //科学计数法
    float f2 = 3e2; // 3 * 10 ^ 2 
    cout << "f2 = " << f2 << endl;
​
    float f3 = 3e-2;  // 3 * 0.1 ^ 2
    cout << "f3 = " << f3 << endl;
​
    system("pause");
​
    return 0;

2.4 字符型

作用:字符型变量用于显示单个字符

语法:char ch = 'a';

注意1:在显示字符型变量时,用单引号将字符括起来,不要用双引号

注意2:单引号内只能有一个字符,不可以是字符串

  • C和C++中字符型变量只占用==1个字节==。

  • 字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放入到存储单元

示例:

int main() 
    
    char ch = 'a';
    cout << ch << endl;
    cout << sizeof(char) << endl;
​
    //ch = "abcde"; //错误,不可以用双引号
    //ch = 'abcde'; //错误,单引号内只能引用一个字符
​
    cout << (int)ch << endl;  //查看字符a对应的ASCII码
    ch = 97; //可以直接用ASCII给字符型变量赋值
    cout << ch << endl;
​
    system("pause");
​
    return 0;

ASCII码表格:

ASCII控制字符ASCII字符ASCII字符ASCII字符
0NUT32(space)64@96
1SOH33!65A97a
2STX34"66B98b
3ETX35#67C99c
4EOT36$68D100d
5ENQ37%69E101e
6ACK38&70F102f
7BEL39,71G103g
8BS40(72H104h
9HT41)73I105i
10LF42*74J106j
11VT43+75K107k
12FF44,76L108l
13CR45-77M109m
14SO46.78N110n
15SI47/79O111o
16DLE48080P112p
17DCI49181Q113q
18DC250282R114r
19DC351383S115s
20DC452484T116t
21NAK53585U117u
22SYN54686V118v
23TB55787W119w
24CAN56888X120x
25EM57989Y121y
26SUB58:90Z122z
27ESC59;91[123
28FS60<92/124|
29GS61=93]125
30RS62>94^126`
31US63?95_127DEL

ASCII 码大致由以下两部分组成:

  • ASCII 非打印控制字符: ASCII 表上的数字 0-31 分配给了控制字符,用于控制像打印机等一些外围设备。

  • ASCII 打印字符:数字 32-126 分配给了能在键盘上找到的字符,当查看或打印文档时就会出现。

2.5 转义字符

作用:用于表示一些==不能显示出来的ASCII字符==

现阶段我们常用的转义字符有:\\n \\\\ \\t

转义字符含义ASCII码值(十进制)
\\a警报007
\\b退格(BS) ,将当前位置移到前一列008
\\f换页(FF),将当前位置移到下页开头012
\\n换行(LF) ,将当前位置移到下一行开头010
\\r回车(CR) ,将当前位置移到本行开头013
\\t水平制表(HT) (跳到下一个TAB位置)009
\\v垂直制表(VT)011
\\\\代表一个反斜线字符""092
'代表一个单引号(撇号)字符039
"代表一个双引号字符034
\\?代表一个问号063
\\0数字0000
\\ddd8进制转义字符,d范围0~73位8进制
\\xhh16进制转义字符,h范围0~9,a~f,A~F3位16进制

示例:

int main() 
    
    
    cout << "\\\\" << endl;
    cout << "\\tHello" << endl;
    cout << "\\n" << endl;
​
    system("pause");
​
    return 0;

2.6 字符串型

作用:用于表示一串字符

两种风格

  1. C风格字符串char 变量名[] = "字符串值"

    示例:

    int main() 
    ​
        char str1[] = "hello world";
        cout << str1 << endl;
        
        system("pause");
    ​
        return 0;
    

注意:C风格的字符串要用双引号括起来

  1. C++风格字符串string 变量名 = "字符串值"

    示例:

    int main() 
    ​
        string str = "hello world";
        cout << str << endl;
        
        system("pause");
    ​
        return 0;
    

注意:C++风格字符串,需要加入头文件==#include<string>==

2.7 布尔类型 bool

作用:布尔数据类型代表真或假的值

bool类型只有两个值:

  • true --- 真(本质是1)

  • false --- 假(本质是0)

bool类型占==1个字节==大小

示例:

int main() 
​
    bool flag = true;
    cout << flag << endl; // 1
​
    flag = false;
    cout << flag << endl; // 0
​
    cout << "size of bool = " << sizeof(bool) << endl; //1
    
    system("pause");
​
    return 0;

2.8 数据的输入

作用:用于从键盘获取数据

关键字:cin

语法: cin >> 变量

示例:

int main()
​
    //整型输入
    int a = 0;
    cout << "请输入整型变量:" << endl;
    cin >> a;
    cout << a << endl;
​
    //浮点型输入
    double d = 0;
    cout << "请输入浮点型变量:" << endl;
    cin >> d;
    cout << d << endl;
​
    //字符型输入
    char ch = 0;
    cout << "请输入字符型变量:" << endl;
    cin >> ch;
    cout << ch << endl;
​
    //字符串型输入
    string str;
    cout << "请输入字符串型变量:" << endl;
    cin >> str;
    cout << str << endl;
​
    //布尔类型输入
    bool flag = true;
    cout << "请输入布尔型变量:" << endl;
    cin >> flag;
    cout << flag << endl;
    system("pause");
    return EXIT_SUCCESS;

C++知识点汇总文档

C++知识点汇总文档

  • 持续更新
  • 朝花夕拾. 不写下来, 仿佛一切都没了见证.
  • 编程来源于生活, 无非是对现实的抽象.
  • 整理这份文档的时候我才发现, 自己对C++的了解无非是冰山一角
  • 另, C++11真的太恐怖了, 新"特性"真的是"恐怖如斯"
  • 另注: 本人才疏学浅, 难免有错漏之处, 还望不吝赐教

1.基本概念


内存管理

  • C++中的内存划分(内容来自博客):
      • 由用户使用new delete关键字管理的内存区域
      • 栈中用来存放临时变量, 比如函数中的局部变量, 在代码块结束时会自动清除
    • 自由存储区
      • 由malloc等分配的内存块, 他和堆是十分相似的, 不过它是用free来结束自己的生命的
    • 全局/静态存储区
      • 全局变量和静态变量被分配到同一块内存中
    • 常量存储区
      • 比较特殊的存储区, 他们里面存放的是常量(不太了解, 有空扫下盲)
  • new 关键字
    • 用来在内存(堆)中开辟一块空间, 用户获得一个指向内存中目标位置的指针
    • 用法参考示例

      //申请一块指向单个int对象的内存, 并将值初始化为"5"
      int *ptr_0 = new int(5);
      
      //申请一块指向5个连续int类型对象的内存
      //使用C++11统一的花括号初始化, 直观地对内存进行初始化
      int * ptr_1 = new int[5]{1,2,3,4,5};
      
  • delete 关键字
    • 删除使用new申请的内存
    • 用法参考示例

      //删除之前申请的内存
      delete ptr_0;
      //删除数组的写法, 注意
      delete [] ptr_1;x
      

左值与右值

  • 左值
    • 左值一般来讲就是变量(能被赋值的), "能出现在等号(赋值号)左边的"都是左值
    • 可以取地址的, 有名字的, 非临时的就是左值
  • 右值
    • "出现在等号右边的临时值"成为右值, 通常情况下C++会产生一个临时变量来存储右值表达式的结果
    • 不能取地址的, 没有名字的, 临时的就是右值

从本质上理解, 创建和销毁由编译器幕后控制, 程序员只能确保在本行代码有效的, 就是右值(包括立即数);
而用户创建的, 通过作用域规则可知其生存期的, 就是左值(包括函数返回的局部变量的引用以及const对象).
摘自博客

  • 左值右值参考示例

    int a{};
    //下式中a是左值, 5+1会产生一个临时变量6, 是右值
    a = 5+1;

引用

  • 左值引用
    • 左值引用是对左值的引用, 类似于为变量起一个别名
    • 常引用
      • 在左值引用时使用const修饰则会成为一个常引用
      • 常引用在引用左值时, 除不能修改引用对象的值以外, 和普通左值引用相同
      • 常引用在引用右值时(如常量), 会生成一个临时变量存储目标值
    • 左值引用参考示例

      int var = 1;
      int &ref = var;   // 定义一个左值引用变量
      ref = 2;          // 通过左值引用修改引用内存的值
      
      //以下语句会报错, 10不是一个合法的左值
      //int &ref0 = 10;
      //用const修饰, 常引用, 引用常量
      const int &ref0 = 10;
      //等价于下面两行代码
      const int temp = 10; 
      const int &ref1 = temp;
      
  • 右值引用
    • 右值引用为C++11中引入的新概念
    • 右值引用的存在是为了减少对象的构造和析构操作, 从而提升效率
    • 底层汇编实现与常引用引用右值时的情况相同, 都使用一个临时变量存储目标值, 不同的是右值引用可以修改引用的值
    • 右值引用参考示例

      //右值引用
      int && rref = 10;
    • 右值引用实际应用参考

      存在如下类定义

      class C  
      {
        public:
          //获得类C的一个实例
          static C getObject() { return C(); }
      };
      //这一行会调用类C的复制构造函数, 参数为getObject()函数产生的临时对象
      //其后临时对象会调用析构函数销毁
      C c = C::getObject();
      
      //右值引用避免了一次中间临时变量的构造与析构过程
      //引用直接指向函数返回时构造的对象
      C &&rref = C::getObject();
      
      一些技巧
      1. 函数返回的内容在函数体外仍然存在的时候(通常是左值), 可以考虑返回引用以提升效率
      2. 函数返回的内容在函数体外不能继续存在的时候(比如函数体中的局部变量, 或右值), 则可以在接受返回值时使用右值引用以提升效率
  • 引用折叠
    • 首先, C++中禁止"引用的引用", 即"reference to reference", 也即不允许引用(动词)一个引用(名词)
    • 当多个引用嵌套时, 采用如下规则折叠(塌缩)引用
      • 所有右值引用折叠到右值引用上仍然是一个右值引用(A&& && -> A&&)
      • 所有的其他引用类型之间的折叠都将变成左值引用(A& & 变成 A&; A& && -> A&; A&& & -> A&)
      • 引用嵌套中出现左值引用则塌缩为左值引用
      • 引用嵌套中全为右值引用则塌缩为右值引用

lambda表达式

  • lambda表达式为C++11中引进的新内容
  • lambda表达式用于定义和使用匿名函数, 可以部分简化编程工作. 但主要用于提高程序可读性, 使程序更加简洁
  • lambda表达式的语法形式

    [捕获列表] (参数列表) 修饰信息 -> 返回值类型 {函数体}
    
    [capture list] (params list) mutable exception-> return-type {function-body}
    • 捕获列表
      • 不可省略, 捕获列表标志着一个lambda表达式的开始
      • 如果捕获字段为[], 则lambda表达式不能访问任何外部变量
      • 字段内可以写入"&"或"="符号来控制访问方式
        • & 表示按引用访问
        • = 表示按值访问
    • 参数列表
      • asdf
    • 修饰信息
      • mutable(可选项): 指示lambda表达式是否能够修改捕获到的变量
      • exception(可选项):
    • 返回值类型
      • 可以省略
      • 当省略返回类型时, 编译器自动推导类型
    • 函数体
      • 匿名函数要执行的语句

面向对象

  • class 关键字
    • class 关键字用以声明一个类
  • 访问控制
    • 三种访问控制
      • public
        • 公有. 所有位置均可访问(包括成员函数, 派生类的成员函数, 非成员函数, 本类或派生类的友元)
      • protected
        • 保护. 只有成员函数, 派生类的成员函数, 派生类的友元, 本类的友元可以访问
      • private
        • 私有. 只有成员函数, 本类的友元可以访问
    • 友元
      • 友元机制提供了一种方案, 它让普通的函数也能访问 类的成员函数能够访问的所有内容
      • 友元的访问权限与成员函数相同. 即: 成员函数可以访问的内容, 友元也都可以访问
      • 需要注意的是, 这里指的"成员函数"和"友元函数"是指同一类中的成员函数和友元函数
        • 举个例子, 派生类的友元是无法访问基类的private成员的. 因为派生类的成员函数也不能访问基类的private成员
    • 访问控制示例

      class C
      {
        friend void fun0(C& c);//友元函数声明
      public:
        int pub;//公有成员
      protected:
        int pro;//保护成员
      private:
        int pri;//私有成员
      };
      
      void fun0(C& c)
      {
        c.pub;
        c.pro;
        c.pri;//没问题, 可以访问
      }
      
      class C_plus:public C//公有继承, 基类成员可见性不变
      {
        friend void fun2(C_plus &c);//友元函数声明
      
        void fun1()
        {
          this->pub;
          this->pro;
          //this->pri;//报错, 不可访问
        }
      };
      
      void fun2(C_plus& c)
      {
        c.pub;
        c.pro;
        //c.pri;//报错, 不可访问
      }
  • 默认的成员函数(如果不手动实现, 编译器会自动实现)
    • 构造函数
      • 当一个新的对象产生的时候调用的函数
      • 构造函数都没有返回值, 也不需要指定void
      • 典型实现

        //"C"为类名
        C();//一个无参构造函数
        {
          //do something
        }
        C(int a, int b)//一个接受两个int值的构造函数
        {
          //do something
        }
    • 析构函数
      • 当一个对象消亡(析构)的时候调用的函数
      • 典型实现

        //"C"为类名
        ~C()
        {
          //do something
          //通常情况下这里会有一些代码用来delete在构造函数中new出的内存指针
        }
    • 复制构造函数(拷贝构造函数)
      • 当使用一个已有的对象创建(初始化)一个新的对象的时候调用的函数
      • 复制构造函数只有一个本类对象的引用作为参数(如果不使用引用会导致无限递归)
      • 复制构造函数的行为涉及到深浅复制的问题
        • 浅复制: 无论成员变量类型为何, 只将成员变量的值复制
        • 深复制: 如果成员变量是一个指针, 则通常不能简单地复制指针的值, 而应该申请新的内存块, 并将得到的指针赋给新的指针类型成员变量
      • 典型实现

        //"C"为类名
        C(const C & another)//必须使用引用作为参数; const可加可不加, 但建议加上
        {
          //do something
        }
    • 转移构造函数(C++11)
      • 当一个已有的对象的内容转移到一个新产生的对象中时调用的函数(一般来说原对象应该要失效)
      • 转移构造函数在针对指针类型的成员变量是通常采取浅复制, 并将被转移的对象的指针成员设为nullptr
      • 典型实现

        //"C"为类名
        C(C && another)
        {
          //do something
        }
    • 赋值函数(赋值操作符重载)
      • 当使用一个已有的对象对另一个已有的对象进行赋值时调用的函数
      • 典型实现

        //"C"为类名
        C& operator=(const C &another)
        {
          //do something
          return * this;
        }
    • 转移赋值函数(赋值操作符重载)(C++11)
      • 当一个已有的对象的内容转移到另一个已有的对象中时调用的函数(一般来说原对象应该要失效)
    • 取地址操作符重载
      • 用于对象的取地址操作, 一般不需要自行实现
      • 典型实现

        //"C"为类名
        C* operator&()
        {
            return this;//直接将地址返回
        }
    • const取地址操作符重载
      • 用于对象的取const地址操作, 一般不需要自行实现
      • 典型实现

        //"C"为类名
        const C* operator&() const
        {
            return this;//直接将地址返回
        }
  • 类型转换构造函数
    • 类型转换构造函数用于将一个其他类型的对象转换为一个类对象
    • 当需要一个类对象, 却提供了一个可以转换为类对象的其他类型的对象时, 自动调用对应的类型转换构造函数进行转换
    • 典型实现

      class C
      {
      public:
        int data;//成员变量
        //类型转换构造函数, 将int类型的值转换为类对象
        /*explicit */C(const int &_data)
        {
          this->data = _data;
        }
      }
    • explicit关键字
      • 有时候, 存在只有一个参数的构造函数, 或存在一个虽然有不止一个参数但除了第一个参数外其余参数都有默认值的构造函数, 但不希望其成为一个类型转换构造函数, 可以使用explicit关键字进行修饰, 它指示该构造函数不是隐式的, 不会自动隐式调用.(注: 用explicit关键字修饰除上述构造函数之外的函数没有意义)
  • 类型转换函数

    C++中, 类型的名字也是一种运算符, 即强制类型转换运算符

    • 主要用于隐式转换, 当需要一个目标类型对象, 却提供了一个类对象时, 自动调用对应的类型转换函数进行转换
    • 典型实现

      class C
      {
      private:
        int data;
      public:
        //转换函数(转换为int类型), 在需求int类型时传递C类的对象会自动调用
        operator int(){ return data; }
      }
  • 在成员函数声明末尾添加const
    • 该操作为成员函数的参数列表中隐含的参数this指针添加const修饰
    • 即: 不允许修改this指针指向的对象; 不允许调用对象的非const成员函数

      //类成员函数
      void fun()const
      {
        //do something
      }
      
      //注:并没有下面这种写法, 只是本质上等价于下面的代码
      
      //"C"为类名
      //注意这里const是修饰类型C的
      //这意味着this指针指向的内容被看作常量
      void fun(const C * this)
      {
        //do something
      }
  • 继承
    • 继承表示了一种"is-A"关系. 即, 派生类是一种(特殊的)基类.
    • 派生类(子类)继承了基类(父类)的所有成员
    • 三种继承方式
      • public (可见性最高, 内外皆可见)
        • 公有继承, 基类的成员在派生类中保持不变(保持在基类中声明的可见性)("成员"包括成员变量和成员函数, 又称字段和方法)
      • protected
        • 保护继承, 基类的成员中, 可见性高于protested的, 在派生类中变为protested
      • private (可见性最低, 对外不可见, 对派生类也不可见)
        • 私有继承, 基类的成员在派生类中可见性变为private
    • 简言之, 比继承方式可见性高的成员, 在派生类中可见性被减弱为继承方式的可见性
    • 成员函数的重载, 重写, 隐藏(这几点很重要, 是C++面向对象中继承的核心)
      • overload(重载)
      • override(重写/覆盖)
      • redefining(重定义/隐藏)
    • 多继承
      • 多继承太麻烦, 说实话也没真正写过代码, 很难保证吃透了. 略过

多态

  • 多态, 指一种事物的多种形态
    • 静态多态, 编译时完成
      • 函数重载
        • 通过对比函数调用与不同的函数原型推断具体调用的函数版本
      • 泛型
        • 对实现了统一接口(这里的接口指同一套操作方案)的不同对象使用同一套模板, 提高代码重用性(鸭子类型)
    • 动态多态
      • 面向对象中的多态
    • 这一节主要是指面向对象中的多态
  • virtual关键字
    • 使用virtual关键字修饰的成员函数称为"虚函数"

泛型

  • C++通过使用模板机制来支持泛型编程
  • 共有两种模板类型
    • 函数模板
    • 类模板
  • 函数模板
    • 未完成待续

move语义


异常处理


2.重要关键字或操作符

decltype

  • decltype是一个关键字, 用于捕获对象的类型
  • 对于左值与右值有着不同的表现
    • 若decltype的目标类型是(被推断为)左值, 则结果为引用类型
    • 若decltype的目标类型是(被推断为)右值, 则结果不为引用类型
  • 由C++11引入

typeid

  • typeid是一个操作符, 用于返回一个对象的类型信息对象
  • 使用typeid后将产生一个type_info类型的对象(C++中唯一创建该对象的方法)
  • 当typeid操作符的操作数是不带有虚函数的类类型时, typeid操作符会指出操作数的声明类型, 而不是底层对象的类型
    • 个人的理解是: 如果操作数的声明类类型中没有任何虚函数, 那么调用该操作数的所有成员函数都将使用其声明类型版本的实现, 那么返回其底层具体类型将没有任何意义
  • 当没有函数需要设为虚的时, 为达到目的可以将析构函数设为虚的. 事实上, 存在派生类的基类的析构函数必须设为虚的, 否则可能因为不调用派生类的析构函数而不能完全释放资源
//示例1
int a{};
//下面这一行语句的输出是"int"
cout << typeid(a).name();

存在如下类定义

class C0
{ };

class C0_plus:public C0   
{ };

class C1
{
protected:
  //虚函数
  virtual ~C1() { }
};

class C1_plus :public C1
{
  virtual ~C1_plus() { }
};
//示例2

C0* p0 = new C0();
//下面的语句输出"class C0"
cout << typeid(*p0).name() << endl;

C0* p1 = new C0_plus();
//下面的语句输出"class C0"
cout << typeid(*p1).name() << endl;

//---------------------

C1* p3 = new C1();
//下面的语句输出"class C1"
cout << typeid(*p3).name() << endl;

C1* p4 = new C1_plus();
//下面的语句输出"class C1_plus"
cout << typeid(*p4).name() << endl;

auto

  • auto关键字早在C++98时就已经存在. 当时用来指示一个变量具有自动的生命周期, 可是一个局部变量总是默认拥有自动生命周期, 因此auto很少被使用, 并且在当时是多余的
  • C++11标准删除了auto关键字的传统用法. 现在, auto关键字用于自动类型推断

    题外话
    显而易见, auto执行的类型推断是在编译时完成的,不会对运行效率有任何影响.
    同时, C++编译器在编译时本身也需要判断声明类型和实际类型是否匹配, 因此应该也不会影响编译速度 (就算影响了也不差这点, 扯远了)

  • C++14后, lambda表达式中的参数捕获也能使用auto
  • auto类型推导可以用于模板, 用以省略模板参数类型的衍生类型在模板参数列表中的声明
    本例摘自博客

    //传统写法, 需要专门为makeObject()的返回值类型在模板的参数列表中添加一项
    template <typename Product, typename Creator>
    void processProduct(const Creator& creator) {  
      Product* val = creator.makeObject();
      // do somthing with val
    }
    
    //使用auto的写法, 得到一定简化
    template <typename Creator>
    void processProduct(const Creator& creator) {
      auto val = creator.makeObject();
      // do somthing with val
    } 

const

class

typename

explicit

delete

using

  • 传统上using关键字用于导入命名空间中的全部或者部分内容
    比如:

    using namespace std;//导入std命名空间中的所有内容
    
    using std::cout;//只导入命名空间std中的cout
  • 但在新的C++中, using可以用于取代typedef
    虽然功能相同但(似乎)更加直观

    //这一条语句为std::string取了一个别名"stdstring"
    using stdstring = std::string;

    可以用在类声明中

    class C
    {
    public:
      using uss = std::string;
      typedef std::string tss;
    };
  • 还有个什么简化声明父类中成员函数的功能, 不是很了解, 到时候再写

mutable

  • 用于labmda表达式, 指示lambda表达式中可以修改捕获到的变量

exception

3.源码剖析

4.一些术语

  • RTTI
    • Run-Time Type Identification: 运行时类型检测

以上是关于c++基础知识汇总的主要内容,如果未能解决你的问题,请参考以下文章

吐血整理:C++编程语言资源汇总

c++语言基础知识汇总

外挂技术汇总及书籍推荐

吐血整理:C++编程语言资源汇总

吐血整理:C++编程语言资源汇总丨第二弹

Perl语言程序应用(资料汇总版)