基本类型

  • wchar_t 长度为16bit,用来存储拓展长度的字符;
  • char16_tchar32_t 用来存储16bit与32bit长度的Unicode编码。

  • char类型与signed char类型不同。

  • 在使用char类型时,必须要规定它是signed char 还是 unsigned char。不能只用char

  • 如果要用到比int大的数字,则使用long long来表示,因为int 一般与long的长度相等。

  • 在使用内置数据类型(例如string或者vector<T>)时,使用string::size_typevector<T>::size_type来表示相应数据类型的大小。

    • 好处是不会溢出。
    • 内部实现是使用typedef常用数据类型。

类型转换

  • 如果将一个溢出值赋予给一个有符号类型,结果将会报错。
  • 有符号数与无符号数相加,有符号数以无符号数读取(如果为负数则读取出错误的值)

立即数(Literals)

  • 正常书写的数字为int型。20==024==0x14
  • 可以通过给立即数增加前缀或后缀来确定一个立即数的类型。
  • 小数默认为double型 IMAGE

  • stringchar型的列表,并在末尾增加了\0。但是strlen()返回的仍然是不加\0的个数。

变量

  • 在函数中,新定义的内建类型是没有初始化的。这种情况下不能访问它。
  • 初始化类对象时,由类来决定初始的值。但是尽量手动初始化所有内建类型的变量。
  • 使用extern可以声明但不定义变量。(extern int i;)

C++ 关键字

IMAGE

  • 系统保留的标识符(Identifier)包括连续两个下划线、下划线后接大写字母、函数外定义的变量不能由下划线开头。

命名习惯

  • 变量名通常是小写字母。
  • 类名通常是大写字母开头。
  • 变量名由多个单词组成的时候用下划线分隔。

作用域

  • 在任何括号之外的域为全局的。
  • 为了更高可读性,应该在第一次使用的时候定义变量,而不是在开头定义。
  • 在变量a为全局变量的情况下,某个代码块中还可以声明局部变量a
    • 代码块内,在声明局部变量之前,访问的a是全局变量。
    • 声明局部变量之后,访问a则为局部变量。
    • 声明局部变量之后,可以使用::a来访问全局变量,全局标识符没有名字,所以留空。

复合类型

引用

  • 声明一个引用时必须初始化。
  • 在绑定了一个变量的引用之后,不能再绑定别的变量。
  • 引用不是对象,而是一个对象的另一个名称。
  • 一个变量可以有多个引用。

指针

  • 指针指向其他类型的变量。
  • 声明null指针,以下三个等价:
    • int *p1 = nullptr
    • int *p1 = NULL
    • int *p1 = 0
  • 不能用整型等变量类型给指针的地址赋值。
  • void*是指向了一个具体的地址,但是没有定义类型,因此它可以指向各种类型的对象。

const修饰词

  • const在创建的时候必须初始化,并且之后不能改变。
  • 在使用立即数对const变量进行赋值时,会直接将变量名变为立即数。
  • 要想在多个源文件中只创建一个const,则需要用extern来定义。
  • 如果用const指针或引用对一个普通变量进行操作,那么它们无法改变这个变量。
  • const reference是const变量的引用,但可以引用int等变量。
  • const分为高级与低级
    • int *const p1 = &i; 等价于 constexpr int *q = nullptr 高级:指针本身是const的
    • const int *p2 = const int c1 = 2; 低级:指针指向的变量是const的。

constexpr修饰词

  • 在初始化一个const类型时,有时不确定初始化的表达式是否为常量,则可以用constexpr来限定初始化表达式必须为常量。目的是为了让编译器检查赋值语句等号右边的变量是const的。
  • const类型可以用变量来进行初始化。

变量类型操作

类型别名

  • typedef double wages;表示可以使用wages代替double
  • using SI = Sales_item;表示可以用SI表示“Sales_item类型”。
  • typedef char *pstring;意思是pstring表示char*

auto

  • 使用auto必须初始化变量,其类型由初始化表达式决定。
  • 在对auto类型变量进行初始化时,有时会与原类型不同
    • 使用引用类型进行初始化时,此变量会被初始化成被引用的变量类型。而引用可以这样写 auto &g = x;
    • auto会忽略top-level的const而保留low-level的const。而top-level的变量可以这样写 const auto f = x;

decltype类型

如果我们需要提取一个表达式的类型,而不需要一个表达式的具体值的时候,可以使用decltype

  • decltype(f()) sum = x;是基本的使用方法。这里编译器只会判断函数f的返回值,而不执行f。
  • decltype可以根据初始化时的类型,来对被初始化的变量类型进行调整。 IMAGE
  • 如果一个变量不加任何括号,则使用变量内容的类型;如果一个变量加括号,则将这个变量当做一个表达式,使用这个表达式本身的类型。 IMAGE

自定义数据结构

结构体

建议用下面第一种方式定义结构体变量,下面两种方式等价。 注意结构体后面的分号!

// method 1
struct Sales_data {
    /*....*/
} accum, trans, *salesptr;

// method 2
struct Sales_data {
    /*....*/
};
Sales_data accum, trans, *salesptr;

自定义头文件

预处理程序从C继承,在编译之前运行,用来替换源代码中的头文件等内容。为了防止一个头文件被多次包含,预处理程序定义了header guards来根据预处理程序变量来判断。预处理程序变量包含两个状态:定义和没定义。 #define命令后面跟一个名称,作为一个预处理变量。

  • #ifdef返回真表示已经被定义过。
  • #ifndef返回真表示还没被定义过。
  • 如果上面的命令返回真,则顺序执行,直到#endif

正常的栗子如下:

#ifndef SALES_DATA_H 
#define SALES_DATA_H 
#include <string> 
struct Sales_data {
    std::string bookNo; 
    unsigned units_sold = 0; 
    double revenue = 0.0;
}; 
#endif
  • 预处理变量名不遵守作用域规则。所以变量名必须在整个程序中是独一无二的。在习惯上我们通常将它全部大写。
  • 在实际项目中,强烈推荐每个头文件都带有header guards,即使只有一个头文件。

static的局部变量

对于一个函数里面的static局部变量,变量存储在代码段。非static的局部变量存储在堆栈段。

  • 下图是带static变量的结果

    int func_test_static(int init){
      if(init > 0){
          static int temp = 9;
          for(int i=0;i<init;i++){
              temp += i;
          }
          return temp;
      }
      return 0;
    }
    

    IMAGE

  • 下图是不带static变量的结果

int func_test(int init){
    if(init > 0){
        int temp = 0;
        for(int i=0;i<init;i++){
            temp += i;
        }
        return temp;
    }
    return 0;
}

IMAGE

  • 下图是使用new操作符存放变量的结果
int func_test_new(int init){
    if(init > 0){
        int* temp = new int;
        for(int i=0;i<init;i++){
            (*temp) += i;
        }
        return *temp;
    }
    return 0;
}

IMAGE

results matching ""

    No results matching ""