傅爷 nb!
# 短路语句
if (a == 'q')
return;
# 一直没有学过去的 malloc
int * a;
a = (int*)malloc(sizeof(int));
*a = 3;
free(a);
# 变量的生存期
C++ (11) 有四种存储变量的方案,这四种方案生成的变量有不同的生存期。
- 自动生存期
用法:函数(或其他语句块 local scope
、函数的形式参数、名称空间)中声明变量。
生存期:函数执行过程中。
这种变量之间没有联系,互不相干(同时也可以用相同的名字)。
函数不能声明在代码块中,不然它就不能在其他函数中被使用,这一点也不“函数”。
- 静态生存期
静态生存期分为三种。
- external linkage(文件间可见)
在 C++ 中,变量有两种声明(declaration)方式:
a. 一种是定义(或定义声明,defining declaration,definition),这种会分配内存;
b. 另一种是引用声明(refering declaration,declaration),不分配内存,只是引用已经存在的变量。
用法:在函数外 int g = 1000;
。
在其他文件使用 g
时,需要加 external
并且不能赋初值(否则 external
无效,是定义声明),这便是引用声明。
显然,如果某变量有引用声明,该变量就只能有一个定义声明。
- internal linkage(单文件中的函数可见)
用法:在函数外 static i = 1000;
。
- 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,其他变量不对其进行初始化(使用空间中的已有值,因此是不固定的)
# 后缀表达式+堆栈=计算题
有点香
# 多文件编写
头文件里有以下部分:
- 函数原型
- 常量(
#define
或const
) - 类和结构的定义(它们不涉及到变量,仅告诉编译器如何创建结构变量)
- 模板的定义(它只告诉编译器如何生成函数的定义)
- 内联函数
- 多个头文件可以相互引用,但是反复引用前记得加
#pragma once
,或者使用#ifndef FILENAME_H_
宏定义判断是否被引用过。 - 结构/类的声明(与其成员函数)、内联函数的定义和非内联函数的声明必须放在
.h
,非内联函数的函数定义必须放在.cpp
里(不然会造成多次编译,参考:为什么c++要“在头文件中声明,在源文件中定义”? - vczh的回答 - 知乎 (opens new window)) - 最后要在
cpp
文件里#include "mycpp.h"
# 工程开发实现一个大的功能(正则匹配器)
先从最简单的功能做起,然后慢慢加功能(不然会手忙脚乱的)
# 函数与过程
函数:
int add(int a, int b)
{
return a+b;
}
过程:
voud foo()
{
game[0] = 1;
game[100] = 100;
}
工程开发偏向纯函数
- 看清函数名、参数和注释,函数过程就不重要了
- 参数一定、返回值一定,测试方便