程序结束状态

一个进程的返回值可以有效协助我们在编写自动化指令时处理程序执行失败的状况,但是在 Windows 与 Linux 指令上有一些区别。共同点在于,在执行结束時都会返回一个代码,通常代码为 0 就是正常,代码不为 0 就是异常。

在 Winows 下只要取得 %ERRORLEVEL% 这个环境变数,在 Linux 下需要取得的是 $? ,即可得知前一个程序所回传的执行结果代码。

Windows 下的 Powershell 是特例,Powershell 中要用 $LastExitCode 。但是 PowerShell 中包含一个与在 Linux Bash 下一模一样的 $? 变量,其变量的类型为 Boolean 并非 Int32 ,此变数只包含执行成功或执行失败的状态,不包括回传的 Int32 代码,使用时要特别注意。

标准IO

C++ 语言中没有定义输入输出,而是一个标准库来提供 IO,iostream。流这个概念的意思是随着时间的推移,数据是顺序产生或者消耗的。

标准库定义了四个 IO 对象,cin,cout,clog,cerr。根据操作系统可以将不同的输出流重定向至不同的文件中。

  1. ./cpp.exe > log.txt 2 > error.txt

命名空间

std::cout 指的是定义在名为 std 的命名空间的 cout,标准库的定义的所有名字都在命名空间 std 中。因此我们想使用标准库的东西时,必须显式地说明想使用来自命名空间 std 中的名字。

:: 就是作用域运算符,std::cout 指出我们想使用定义在命名空间 std 中的 cout。

build-in(内置类型)

C++ 定义了包括算数类型和空类型在内的基本数据类型,相比较 C 语言 C++ 补充了布尔类型,给程序员提供了一个标准化的 bool 类型。而 C 要使用布尔需要引入 stdbool.h 库。

算数类型分成整型和浮点型,算数类型的尺寸在不同机器上不一样,但是规定了尺寸的最小值,允许编译器赋予这些类型更大的尺寸。

整型建议使用 cstdint 库中的类型。

类型 含义 最小尺寸
bool 布尔 未定义
char 字符 8位
wchar_t 宽字符 16位
char16_t Unicode字符 16位
char32_t Unicode字符 32位
short 16位
int 16位
long 32位
long long 64 位
float 6位有效数字
double 10位有效数字
long double 10位有效数字

char 用来提供最小字符集,wchar_t 用来存放机器最大扩展字符集中的任意字符,char16_t 和 char32_t 用来存放 unicode 字符。

对象和类型

对象是类型的实例,不只是类的实例。实例包含了标识符作为名称,对应的内存地址,内存中的值。类型有内置类型,自定义类型。0

字面值常量

整型字面值(8,16,10 进制)十进制的字面值是带符号的,其他的可能是带符号的。十进制的字面值是三个整型(没有short)中尺寸最小的那个,前提是可以存放下 。

八进制和十六进制除了三种整型(没有short)还要加上三种无符号整型中的尺寸最小者,前提是可以存放下 。如果一个字面值连最大的数据类型都放不下就会错误。字面值是没有负数的,只是将字面值负数运算。

浮点数字面值,是 double 类型。

字符和字符串,是 char 和 char 数组。”hello”,它的类型是 const char [6],而非 const char 类型,在模板传参要格外小心,因为模板退化是是可以退化为 const char。再进一步: “aaaa”,它的类型是 const char [5],而const char [6] 与 const char [5] 就不是一个类型,这点要注意哦,只是退化时都变成 const char*,这时又可以传参进去。c++ 保留了 c 风格的字符串即遇到 ‘\0’ 视为字符串结束。

布尔值,是 true 和 false。

指针,是 nullptr

可以通过给字面值加前缀和后缀来指定字面值的数据类型。字符和字符串是前缀,整型和浮点型是后缀。

初始化和赋值

初始化不是赋值,初始化就是创建变量时赋予其中一个初始值,而赋值的含义是把对象的当前值擦除而以一个新值来代替。

如果定义时没有指定初始值,变量被默认初始化,此时变量被赋予了默认值,默认值是什么有变量类型和定义变量位置决定。

如果内置类型的变量未被显示初始化,它的值由定义位置决定,定义于任何函数之外的变量被初始化为 0 ,定义于任何函数之内的变量将不被初始化,此时是 UB 的由编译器决定。

  1. int a = 0;
  2. int b = {0};
  3. int c{0};
  4. int c(0);

上面四种都可以初始化,C11 之后可以用花括号初始化内置变量,由于 C11 之前在类中使用的缘故,被称为列表初始化。第一种是 c 语言时期就有的方式,列表初始化更严格 int a {1.1} 会报错。

int(1) 这种初始化方式可以在模板中使用,T(1)于是 build-in 类型和类的初始化在模板中就一致了。

构造函数

  1. int c(0);

虽然上面写法和构造函数很像,但是内置类型没有真正的构造函数。构造函数分为概念上的构造函数形式和真正的构造函数。

在很多书上会说这样初始化会调用系统的 int 默认构造函数,但是实际上概念上的构造函数(int 也不可能有构造函数),只是简单的以 0 初始化,编译器没有调用任何函数,只是简单的给他赋值 0。

static 变量

静态局部变量是有作用域的,静态全局变量的作用域是文件作用域不被外部源文件调用。而全局变量可以被其他源文件 extern 使用。

  1. int main()
  2. {
  3. {
  4. static int a = 1;
  5. }
  6. std::cout << a;
  7. }

条件表达式

? 后面和 : 后面的对象的类型,原则上不可以一样编译阶段就会报错,但是如果两者可以互相转换则可以。