1. 指针
#include <iostream>
using namespace std;
int sum(int ar2[][4], int size) {
int total = 0;
for (int r = 0; r < size; r++) {
for (int c = 0; c < 4; c++)
total += ar2[r][c];
}
return total;
}
int main() {
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
int total = sum(arr, 3);
cout << total << endl;
cout << "arr[0][0] 的地址:" << arr << endl;
cout << "arr[1][0] 的地址:" << arr + 1 << endl;
cout << "arr[1][0] 的值:" << *(*(arr + 1)) << endl;
cout << "arr[1][2] 的值:" << *(*(arr + 1) + 2) << endl;
cout << "arr[1][2] 的地址:" << *(arr + 1) + 2 << endl;
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
int *p = a, *q = a;
// 一维数组取地址
cout << "方法一:p(+i) 首元素地址" << p << '\t' << "p[2] 的地址" << p + 2 << endl;
cout << "方法二:a(+i) 首元素地址" << a << '\t' << "p[2] 的地址" << a + 2 << endl;
cout << "方法三:&p[] 首元素地址" << &p[0] << '\t' << "p[2] 的地址" << &p[2] << endl;
cout << "方法四:&a[] 首元素地址" << &a[0] << '\t' << "p[2] 的地址" << &a[2] << endl;
cout << "结论:a 与 p 完全等价" << endl;
// 一维数组取值
cout << "方法一:*(p+i) 首元素的值" << *p << '\t' << "a[2] 的值" << *(p + 2) << endl;
cout << "方法二:*(a+i) 首元素的值" << *a << '\t' << "a[2] 的值" << *(a + 2) << endl;
return 0;
}
2. static 关键字
#include <iostream>
using namespace std;
int fun() {
static int i = 0;
int s = 1;
s += i;
i++;
return s;
}
int main() {
int i, a = 0;
for (i = 0; i < 5; i++) {
a += fun();
}
cout << a << endl;
return 0;
}
结果:15
在程序中,
static关键字修饰了函数fun()中的局部变量i,使其成为静态局部变量,具有以下关键特性:1. 延长生命周期
- 普通局部变量:在函数调用时创建,函数返回时销毁。
- 静态局部变量:在程序开始运行时分配内存,直到程序结束才销毁(生命周期与全局变量相同)。
2. 保持值的持久性
变量
i的值在函数调用之间保持不变:
- 第一次调用
fun()时,i被初始化为 0。- 后续每次调用
fun()时,i都保留上一次调用结束时的值。- 初始化
=0只执行一次。3. 作用域仍局限于函数内
尽管生命周期是全局的,但
i的作用域仍然只在fun()函数内部,外部代码无法直接访问它。
3. 循环变量作用域
#include <iostream>
using namespace std;
void f(float *p, float &b, int n) {
int l;
for (l = 0; l < n; l++)
b += *p++;
b /= l;
}
const int N = 6;
int main() {
int l;
float a[N] = {1, 2, 3, 4, 5};
float c = 0;
f(a, c, N);
cout << c << endl;
return 0;
}
答案:2.5
计算过程:(1+2+3+4+5)/6
4. 复制构造函数的调用
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass(int n) { number = n; }
MyClass(MyClass &other) {
number = other.number;
cout << "调用了复制构造函数" << endl;
}
~MyClass() {}
private:
int number;
};
MyClass fun(MyClass p) {
MyClass temp(p);
return temp;
}
int main() {
MyClass obj1(10), obj2(0);
MyClass obj3(obj1);
obj2 = fun(obj3);
return 0;
}
调用了 4 次
详细分析:
MyClass obj3(obj1);:用obj1初始化obj3,调用 1 次复制构造函数。- 函数调用
fun(obj3)时的参数传递:形参p通过值传递的方式用obj3初始化,调用 1 次复制构造函数。fun函数内部定义temp对象:MyClass temp(p);用p初始化temp,调用 1 次复制构造函数。fun函数返回temp对象:返回temp时,编译器生成临时对象,调用 1 次复制构造函数(假设无编译器优化)。
注意:赋值操作
obj2 = fun(obj3);使用默认的赋值运算符,不调用复制构造函数。第 4 次复制构造函数的调用发生在函数返回创建临时对象时。
5. 在有序数组中插入一个数
#include <iostream>
using namespace std;
int main() {
int a[10] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int n;
cin >> n;
int j = 9;
while (j >= 0 && n < a[j]) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = n;
for (int i = 0; i < 11; i++)
cout << a[i] << ' ';
cout << endl;
return 0;
}
6. 算式填空问题
#include <iostream>
using namespace std;
int main() {
int ei;
cin >> ei;
int x[3]; // x[0]+x[1]=x[2]
int c[10] = {0}; // 标记 0~9 哪些数字用过了
int r; // 一共用了 r 个数
int s = 0; // 一共有 s 个式子
int tx = 0, ty = 0;
int i, t;
for (x[0] = 102; x[0] <= 493; x[0]++)
for (x[1] = x[0] + 1; x[1] <= 987 - x[0]; x[1]++) {
x[2] = x[0] + x[1];
for (i = 0; i < 3; i++) {
t = x[i];
do {
c[t % 10] = 1;
t /= 10;
} while (t != 0);
}
r = 0;
for (i = 0; i < ; i++) r += c[i], c[i] = ;
(r == ) {
s++;
(s == ei) tx = x[], ty = x[];
}
}
cout << << s << << endl;
(ei <= s)
cout << ei << << tx << << ty << << tx + ty << endl;
cout << << endl;
;
}
7. 字符串子串查找
#include <iostream>
using namespace std;
int main() {
char s1[100];
char s2[100];
cin >> s1;
cin >> s2;
int len1 = 0, len2 = 0;
while (s1[len1] != '\0') len1++;
while (s2[len2] != '\0') len2++;
bool found = false;
if (len2 <= len1) {
int i = 0;
while (i < len1 - len2) {
int j = 0;
bool match = true;
while (j < len2) {
if (s1[i + j] != s2[j]) {
match = false;
break;
}
j++;
}
if (match) {
cout << i << ' ';
found = true;
i += len2;
} else {
i++;
}
}
}
if (!found) {
cout << -1 << endl;
} else {
cout << endl;
}
return 0;
}
8. 用指针访问二维数组
(1)通过函数
#include <iostream>
using namespace std;
void printArray(int (*arr)[4], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 4; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
}
int main() {
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
printArray(arr, 3);
return 0;
}
(2)使用数组指针
#include <iostream>
using namespace std;
int main() {
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
int *p = &arr[0][0];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
cout << *(p + i * 4 + j) << " ";
}
cout << endl;
}
return 0;
}
(3)数组指针
#include <iostream>
using namespace std;
int main() {
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
int (*p)[4] = arr; // 数组指针——指向包含 4 个 int 的数组
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
cout << p[i][j] << " ";
}
cout << endl;
}
return 0;
}
*C++ 中,a[i] 相当于 (a+i),a[i][j] 相当于 ((a+i)+j)
9. 字符串处理函数
#include <cstring>
// strcat // 字符串连接
// strcpy // 复制
// strcmp // 比较
// strlen // 求长度
// strlwr // 转换为小写
// strupr // 转换为大写
10. 查找算法(二分查找)
#include <iostream>
using namespace std;
int main() {
int array[] = {2, 5, 7, 8, 9, 11, 23, 26, 32, 37};
int high, low, mid, a;
low = 0;
high = 9;
cin >> a;
mid = (low + high) / 2;
while (array[mid] != a && low <= high) {
if (a > array[mid])
low = mid + 1;
else
high = mid - 1;
mid = (low + high) / 2;
}
if (array[mid] == a)
cout << "exist:" << mid + 1 << endl;
else
cout << "no exist" << endl;
return 0;
}
11. 排序算法(冒泡排序)
#include <iostream>
using namespace std;
int main() {
int array[10] = {9, 7, 8, 5, 10, 4, 6, 2, 1, 3};
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10 - i - 1; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
for (int i = 0; i < 10; i++)
cout << array[i] << ' ';
cout << endl;
return 0;
}
12. 变量的生存期
- 内存分区:
- 数据区:
- 动态数据区(栈区):变量离开作用域,生存期终止;数据如果没有给出初始值,为随机值。
- 静态数据区:和程序一样长的生存期,一直占用内存空间。全局变量与静态变量储存在此处。数据如果没有给出初始值,自动初始化为 0。
- 代码区
- 数据区:
如果一个变量结束了其生存期,那么该变量就离开了其作用域。 如果一个变量结束了其作用域,那么该变量不一定就结束了生存期。
- 用
static声明局部变量:分配在静态数据区。 - 用
extern声明全局变量。
13. 复制构造函数调用的三个情境
(1)初始化
MyClass Wuhan(Beijing);
(2)函数的形参为对象时
系统创建临时形参对象,并将实参对象的值赋值给形参对象(系统自动调用)。
void fun1(MyClass c1) { c1.showTime(); }
fun1(Beijing);
(3)当函数返回值的是对象时
系统自动调用复制构造函数。
MyClass fun2() {
MyClass A(13, 0, 0);
return A;
}
MyClass Munich;
Munich = fun2();
注意复制和赋值的区别!
14. 空指针错误分析
编译运行以下程序的结果是什么?
#include <iostream>
using namespace std;
int main() {
char *p = 0;
*p = 'a';
cout << *p;
return 0;
}
这个程序存在严重的运行时错误,会导致程序崩溃(通常是段错误 Segmentation Fault)。
程序问题分析
char *p = 0;:将指针p初始化为空指针(nullptr/NULL)。这意味着p不指向任何有效的内存地址。*p = 'a';:尝试解引用空指针并写入字符'a'。这是未定义行为。操作系统会阻止程序访问地址 0 的内存,导致段错误。cout << *p;:即使能执行到这里,也是解引用空指针读取数据,同样会导致段错误。
15. 类和对象构造次数
-
构造函数可以重载,析构函数不可以。
-
对象定义:
class A { // ... }; A a, b(3), c[4], *p;调用了多少次构造函数? 6 次!
a(1) +b(1) +c[0~3](4)。*p只是指针,不调用构造函数。A* a = new A[5];5 次!
A* a = new A;1 次!(与
*p做区分)

