傅爷 nb!

短路语句

1
2
if (a == 'q')
return;

一直没有学过去的 malloc

1
2
3
4
int * a;
a = (int*)malloc(sizeof(int));
*a = 3;
free(a);

变量的生存期

C++ (11) 有四种存储变量的方案,这四种方案生成的变量有不同的生存期。

  • 自动生存期

用法:函数(或其他语句块 local scope、函数的形式参数、名称空间)中声明变量。
生存期:函数执行过程中。

这种变量之间没有联系,互不相干(同时也可以用相同的名字)。

函数不能声明在代码块中,不然它就不能在其他函数中被使用,这一点也不“函数”。

  • 静态生存期

静态生存期分为三种。

  1. external linkage(文件间可见)

在 C++ 中,变量有两种声明(declaration)方式:
a. 一种是定义(或定义声明,defining declaration,definition),这种会分配内存;
b. 另一种是引用声明(refering declaration,declaration),不分配内存,只是引用已经存在的变量。

用法:在函数外 int g = 1000;

在其他文件使用 g 时,需要加 external 并且不能赋初值(否则 external 无效,是定义声明),这便是引用声明。

显然,如果某变量有引用声明,该变量就只能有一个定义声明。

  1. internal linkage(单文件中的函数可见)

用法:在函数外 static i = 1000;

  1. no linkage(仅在一个函数/代码块可见)

用法:在函数内 static t = 1000;

这三种变量都会在程序运行过程中一直存在。由于这部分变量占用内存是不变的,程序干脆在运行的一开始,就分配一块内存来存这些静态变量。

编译器还会隐式自动将静态生存期的变量按位模式初始化为 0。对于有用常量表达式赋初值的静态变量,编译器会做一些计算(注意是编译器来做,sizeof 也算是这种计算,另外 C++ 11 后的 constexpr 也被包含在内);对于复杂的(如,需调用函数),则需要动态初始化。

  • 动态生存期

用法及生存期:从 new 开始,直到 delete

这之中包含了 register 变量。在 C++ 11 以前,register 变量会使用 CPU 缓存进行存储,对于频繁访问的变量使用 register 能够是程序更快。
不过在 C++ 11 以前,也有编译器会自动进行处理,不需要手动 register。C++ 11 直接弃用了 register,把这步完全交给了编译器,register 更像是提示程序员,该变量会被反复使用。

  • 线程生存期

并行运算使用,C++ 11 后。

内存分配

内存空间分为四个部分:静态数据区、代码区、栈区、堆区。

  • 静态数据区:全局变量、static存储类的局部变量、常量
  • 代码区:函数代码
  • 栈区:auto存储类的局部变量、函数的形参、函数调用时的有关信息(如返回值)
  • 堆区:动态变量

静态数据区和代码区的大小是固定的,而栈区和堆区的大小随程序的运行不断变化(不过操作系统会对其空间最大值有一定的限制)。

编译程序隐式自动将静态生存期的变量按位模式初始化为 0,其他变量不对其进行初始化(使用空间中的已有值,因此是不固定的)

后缀表达式+堆栈=计算题

有点香

多文件编写

头文件里有以下部分:

  • 函数原型
  • 常量(#defineconst
  • 类和结构的定义(它们不涉及到变量,仅告诉编译器如何创建结构变量)
  • 模板的定义(它只告诉编译器如何生成函数的定义)
  • 内联函数
  1. 多个头文件可以相互引用,但是反复引用前记得加 #pragma once,或者使用 #ifndef FILENAME_H_ 宏定义判断是否被引用过。
  2. 结构/类的声明(与其成员函数)、内联函数的定义和非内联函数的声明必须放在 .h,非内联函数的函数定义必须放在 .cpp 里(不然会造成多次编译,参考:为什么c++要“在头文件中声明,在源文件中定义”? - vczh的回答 - 知乎
  3. 最后要在 cpp 文件里 #include "mycpp.h"

工程开发实现一个大的功能(正则匹配器)

先从最简单的功能做起,然后慢慢加功能(不然会手忙脚乱的)

函数与过程

函数:

1
2
3
4
int add(int a, int b)
{
return a+b;
}

过程:

1
2
3
4
5
voud foo()
{
game[0] = 1;
game[100] = 100;
}

工程开发偏向纯函数

  1. 看清函数名、参数和注释,函数过程就不重要了
  2. 参数一定、返回值一定,测试方便