C++ 快速复习指南(上半部分)
1.基础语法
基本结构
#include <iostream> 头名
using namesapce std ; 统一使用命名空间 int main () { 程序执行门户 主题内容}
基本输出
cout << "string " << endl;
// 输出 string
变量和数据类型 格式
int intger = 10 ;
常量的引入 需要在变量前面添加const
例如 const float pi = 3.1415926
基本输入
int input 定义一个input变量
cin >> input ; 输入语句
2.控制结构
if 语句 while switch for 循环
//if 语句 条件控制语句#include <iostream> 用于引入cout 和cin 语句using namespace std;
int main () {
int number =15; 变量后面要分号 用于断点if (number>15) {cout << a << endl;}else if ( number =15) {cout << b << endl;}else {cout << c << endl;}// switch 语句 轮询switch (number) {case 10: //注意此处switch语句中case后面添加的是冒号而非是分号cout << "a" << endl; break;// 截止符号 或者使用return 加具体值case 15:cout << "b" << endl; break;default: cout << "other" << endl;} // 循环语句//for 语句 遍历 for (int i =0 ; i < 5 ; i++ ) { cout << "for循环:" << i << "遍" << endl;}//while 语句 //先定义一个变量j=0while (j<3){cout << "while循环" << "j" << endl ;j++; // 让j变量动起来不然j变量不变 while循环输出结果不变}//do-while循环 int k =0;do { cout << "do-while 循环 " << k << endl;k++;}while (k<2);return 0; //do-while 循环是while循环的反过来 先定义循环动作, 再定义循环条件 }
3.函数
#include <iostream>
using namesapce std;
//函数声明和定义都要main()入口外围书写
//函数声明
int add(int a ,int b);
void pringmessage(string message);//重载
double add(double a, double b);
//在函数的定义中可以使用实参//内联函数 在函数类型前加上inline 可以在代码体中直接插入函数
//必须声明和定义在头文件中
inline 返回类型 函数名(参数列表) {// 函数体
}inline int multiply(int a ,int b) {return a *b ;
}int main () {//主体部分
}
//函数的定义
int add (int a ,int b ){return a+b ;
}
....
C++ 函数类型对比表
函数类型特性对比
函数类型 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
普通函数 | ✅ 代码复用性好 ✅ 易于调试维护 ✅ 支持分离编译 ✅ 适合复杂逻辑 | ❌ 函数调用有开销 ❌ 性能相对较低 ❌ 需要头文件管理 ❌ 不适合极频繁调用 | 大型复杂函数 需要调试的函数 跨文件使用函数 包含I/O操作的函数 |
内联函数 | ✅ 消除调用开销 ✅ 提高性能 ✅ 编译时优化 ✅ 适合小型函数 | ❌ 可能导致代码膨胀 ❌ 调试困难 ❌ 不能是虚函数 ❌ 不适合复杂函数 | 小型函数(1-5行) 频繁调用的函数 简单数学运算 getter/setter方法 |
模板函数 | ✅ 类型安全泛型 ✅ 代码复用性高 ✅ 编译时多态 ✅ 性能优秀 | ❌ 编译时间较长 ❌ 错误信息难懂 ❌ 可能导致代码膨胀 ❌ 调试困难 | 通用算法实现 容器类操作 数学库函数 多数据类型支持 |
Lambda表达式 | ✅ 简洁匿名函数 ✅ 方便闭包功能 ✅ 适合STL算法 ✅ 减少代码量 | ❌ 过度使用降低可读性 ❌ 复杂lambda难理解 ❌ 调试相对困难 ❌ 性能可能略低 | STL算法回调 一次性简单函数 需要捕获变量 函数式编程风格 |
constexpr函数 | ✅ 编译时计算 ✅ 零运行时开销 ✅ 类型安全 ✅ 适合数学计算 | ❌ 函数体限制多 ❌ 不能有I/O操作 ❌ 调试困难 ❌ C++11限制多 | 编译时常量计算 数学库函数 模板元编程 高性能计算 |
静态成员函数 | ✅ 不依赖对象实例 ✅ 命名空间组织 ✅ 工具函数集合 ✅ 线程安全 | ❌ 不能访问非静态成员 ❌ 可能破坏封装性 ❌ 可能被滥用 ❌ 全局状态管理复杂 | 工具函数集合 工厂方法 单例模式 不依赖对象状态的函数 |
虚函数 | ✅ 运行时分发 ✅ 多态支持 ✅ 接口设计灵活 ✅ 易于扩展 | ❌ 虚函数调用开销 ❌ 对象大小增加 ❌ 调试复杂 ❌ 可能被误用 | 多态接口设计 框架和库开发 插件系统 运行时动态绑定 |
4.数组和字符串
普通数组的定义
int num [5] ={1,2,3,4,5}
数组类型 数组名字 元素个数 集合
for循环遍历数组
//传统写法
for (int i =0;i<5 ; i++) {cout << num[i]<<endl;
}
//c++11 for循环语法糖
for (int num :n) {cout << num
}
array 固定大小的数组容器
array <int,5> arr ={1,2,3,4,5}类型,大小
arr.size() 数组大小
输出字符串长度
string str= "hello";cout << str.length<<endl;
动态数组 vector
vector <int> vec ={10,20,30}
// 类型 name date遍历方法同普通数组 1,传统遍历 2,使用语法糖vec.push_back(50); //向动态数组中直接添加元素,此处是不同于普通数组和array的区别,不需要先扩容再添加
5.指针和引用
1.内存布局
int var =20 ;
/var
内存地址 01000
变量名 var
值 20
*/
2指针详解
2.1指针的基本操作
int* ptr =&var ; //int* ptr 表示指针, &var 获取var的内存地址
cout << "变量值: " << var << endl; // 输出: 20
cout << "指针地址: " << ptr << endl; // 输出: 0x1000 (var的地址)
cout << "指针指向的值: " << *ptr << endl; // 输出: 20 (*ptr 解引用)
指针操作图解:
var: [ 20 ] ← 变量本身地址: 0x1000ptr: [ 0x1000 ] ← 存储var的地址*ptr = 20 ← 通过ptr访问var的值
3.引用详解
3.1引用本质
int var = 20;
// 引用定义和初始化
int& ref = var; // ref是var的别名cout << "var: " << var << endl; // 输出: 20
cout << "ref: " << ref << endl; // 输出: 20ref = 30; // 通过引用修改变量值cout << "修改后var: " << var << endl; // 输出: 30
cout << "修改后ref: " << ref << endl; // 输出: 30由此可以看出引用其实就是共享, 两个变量名字共享一个内存地址
引用操作图解
var: [ 30 ] ← 原始变量↑
ref: [别名] ← ref是var的别名,共享同一内存
4.动态内存分布
//语法结构int* dynamicPtr = new int;// 在堆上分配int大小的内存*dynamicPtr = 100; //在分配的内存中存储值cout << "动态分配的值: " << *dynamicPtr << endl;delete dynamicPtr; // 释放内存 解除资源占用
5.动态数组
int size = 5;int* arr = new int[size]; // 在堆上分配数组for (int i = 0; i < size; i++) {arr[i] = i * 10; // 初始化数组元素}delete[] arr; // 释放数组内存,注意使用delete[]return 0;
}
指针 vs 引用
特性 | 指针 | 引用 |
---|---|---|
定义 | int* ptr = &var; | int& ref = var; |
可空性 | 可以为nullptr | 必须初始化,不能为空 |
重指向 | 可以指向其他变量 | 一旦初始化不能改变 |
内存占用 | 占用内存存储地址 | 不占用额外内存(编译器实现) |
操作符 | *ptr 解引用 | 直接使用 |
6.类和对象
1. 类的基本结构
类定义分析
class Person {
private:string name;int age;public:// 构造函数Person() : name("Unknown"), age(0) {} //defaultPerson(string n, int a) : name(n), age(a) {} //parameterized// 拷贝构造函数Person(const Person& other) {name = other.name;age = other.age;}// 析构函数~Person() {cout << name << "对象被销毁" << endl;}// 成员函数void display() const {cout << "姓名: " << name << ", 年龄: " << age << endl;}// setter 和 gettervoid setName(string n) { name = n; }string getName() const { return name; }void setAge(int a) { age = a; }int getAge() const { return age; }// 静态成员static int count;
};
2. 访问控制说明符
private 私有成员
private:string name;int age;
- 作用:只能在类内部访问
- 特点:外部代码无法直接访问,通过public的setter/getter方法间接访问
- 目的:数据封装,保护数据安全
public 公有成员
public:// 构造函数、成员函数等
- 作用:可以在类外部访问
- 特点:提供类的对外接口
- 包含:构造函数、析构函数、成员函数等
protected 保护成员(补充)
protected:string protectedData;
- 作用:类内部和派生类中可以访问
- 特点:外部代码不能访问
- 用途:继承体系中使用
3. 构造函数详解
默认构造函数
Person() : name("Unknown"), age(0) {}
- 作用:创建对象时自动调用
- 初始化列表:
: name("Unknown"), age(0)
- 在函数体执行前初始化成员变量 - 调用时机:
Person person1;
参数化构造函数
Person(string n, int a) : name(n), age(a) {}
- 作用:接受参数来初始化对象
- 优点:使用初始化列表提高效率(避免先默认初始化再赋值)
- 调用时机:
Person person2("Alice", 25);
拷贝构造函数
Person(const Person& person2) {//这个括号里面的person其实就是一个参数,person2才是source函数name = person2.name;age = person2.age;
}
- 作用:用于对象复制
- 参数:
const Person& other
- 常量引用,避免不必要的拷贝 - 函数调用:
Person person1 = person2;//调用person创建p1去拷贝p2
4. 析构函数
cpp
~Person() {cout << name << "对象被销毁" << endl;
}
- 作用:对象销毁时自动调用,用于资源清理
- 命名:类名前加
~
- 调用时机:对象离开作用域或被delete时
5. 成员函数
普通成员函数
cpp
void display() const {cout << "姓名: " << name << ", 年龄: " << age << endl;
}
- const关键字:承诺不修改成员变量
- 作用:提供对象的行为功能
setter 和 getter 方法
cpp
void setName(string n) { name = n; } // 设置器
string getName() const { return name; } // 获取器(const)
void setAge(int a) { age = a; } // 设置器
int getAge() const { return age; } // 获取器(const)
- 目的:控制对私有成员的访问
- 优点:可以在setter中添加验证逻辑
6. 静态成员
静态变量声明
cpp
static int count; // 类内声明
静态变量定义
cpp
int Person::count = 0; // 类外定义和初始化
- 特点:所有对象共享同一个静态变量
- 访问方式:
类名::静态成员名
或对象.静态成员名
- 用途:统计对象数量、共享数据等
7. 对象创建和使用
对象创建方式
cpp
// 栈上创建(自动管理内存)
Person person1; // 调用默认构造函数
Person person2("Alice", 25); // 调用参数化构造函数// 堆上创建(动态内存,需要手动管理)
Person* person3 = new Person("Charlie", 30);
delete person3; // 必须手动释放
成员访问
cpp
person1.setName("Bob"); // 调用成员函数设置值
person1.setAge(30);
cout << person1.getName(); // 调用成员函数获取值person1.display(); // 调用显示功能
8.完整项目展示
头文件和源文件分离
头文件 (person.h)
#ifndef PERSON_H
#define PERSON_H#include <string>
using namespace std;class Person {
private:string name;int age;public:// 构造函数Person();Person(string n, int a);Person(const Person& other);// 析构函数~Person();// 成员函数void display() const;// setter 和 gettervoid setName(string n);string getName() const;void setAge(int a);int getAge() const;// 静态成员static int count;
};#endif
源文件(person.cpp)
#include "person.h"
#include <iostream>
using namespace std;// 静态成员初始化
int Person::count = 0;// 构造函数实现
Person::Person() : name("Unknown"), age(0) {count++;
}Person::Person(string n, int a) : name(n), age(a) {count++;
}Person::Person(const Person& other) : name(other.name), age(other.age) {count++;
}// 析构函数实现
Person::~Person() {cout << name << "对象被销毁" << endl;count--;
}// 成员函数实现
void Person::display() const {cout << "姓名: " << name << ", 年龄: " << age << endl;
}void Person::setName(string n) {name = n;
}string Person::getName() const {return name;
}void Person::setAge(int a) {age = a;
}int Person::getAge() const {return age;
}
主程序main()
#include <iostream>
#include "person.h"
using namespace std;int main() {cout << "初始对象数量: " << Person::count << endl;// 创建对象Person person1;Person person2("Alice", 25);person1.setName("Bob");person1.setAge(30);person1.display();person2.display();cout << "当前对象数量: " << Person::count << endl;{Person person3("Charlie", 35); // 新作用域person3.display();cout << "作用域内对象数量: " << Person::count << endl;} // person3在这里被销毁cout << "最终对象数量: " << Person::count << endl;return 0;
}