函数的分文件编写
作用:让代码结构更加清晰
函数分文件编写一般有4个步骤
创建后缀名为.h的头文件
创建后缀名为.cpp的源文件
在头文件中写函数的声明
在源文件中写函数的定义
指针和函数
作用:利用指针作函数参数,可以修改实参的值
示例:
//值传递
void swap1(int a ,int b)
{
int temp = a;
a = b;
b = temp;
}
//地址传递
void swap2(int * p1, int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main() {
int a = 10;
int b = 20;
swap1(a, b); // 值传递不会改变实参
swap2(&a, &b); //地址传递会改变实参
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause");
return 0;
}
总结:如果不想修改实参,就用值传递,如果想修改实参,就用地址传递
- const修饰指针
const修饰指针有三种情况
const修饰指针 --- 常量指针
const修饰常量 --- 指针常量
const即修饰指针,又修饰常量
空指针(Null Pointer)
定义:
空指针指的是 明确赋值为 nullptr(C++11及以后)或 NULL(C 语言) 的指针,表示“什么也不指”。
int* ptr = nullptr; // C++11
int* ptr = NULL; // C 风格
常见错误:
int* ptr = nullptr;
*ptr = 42; // ❌ 运行时崩溃(段错误)
检查方式:
if (ptr != nullptr) {
// safe to dereference
}
野指针(Wild Pointer)
定义:
野指针指的是:
未初始化的指针
指向已经释放的内存
它们“看起来有地址”,但 这个地址不合法或不可控,使用极其危险。
🚨 示例 1:未初始化的指针
int* p; // ❌ 没有初始化,p 指向未知内存
*p = 10; // ❌ 随机内存写入 → 崩溃 or 写乱内存
🚨 示例 2:悬垂指针(Dangling Pointer)
int* p;
{
int a = 10;
p = &a;
} // a 生命周期结束
*p = 20; // ❌ 悬垂指针,访问已销毁变量
🚨 示例 3:释放后未置空
int* p = new int(5);
delete p;
*p = 10; // ❌ 指向已释放内存(悬垂)
p = nullptr; // ✅ 建议 delete 后立即置空
https://github.com/Blitzer207/C-Resource/blob/master/第3阶段-C%2B%2B核心编程 资料/讲义/C%2B%2B核心编程.md

引用
1.给变量起别名
2.必须先初始化
3.给函数做参数
//1. 值传递
void mySwap01(int a, int b) {
int temp = a;
a = b;
b = temp;
}
//2. 地址传递
void mySwap02(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
//3. 引用传递
void mySwap03(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 10;
int b = 20;
mySwap01(a, b);
cout << "a:" << a << " b:" << b << endl;
mySwap02(&a, &b);
cout << "a:" << a << " b:" << b << endl;
mySwap03(a, b);
cout << "a:" << a << " b:" << b << endl;
system("pause");
return 0;
}
-
值传递 mySwap01
void mySwap01(int a, int b)
调用时传的是 a 和 b 的副本。
函数内部修改的是 副本的值,不会影响 main 中的 a 和 b。
所以调用完后 a = 10, b = 20 不变。
🔹2. 地址传递(指针)mySwap02
void mySwap02(int* a, int* b)
调用时传的是变量 a 和 b 的地址(即 &a, &b)。
在函数中通过 a、b 来修改原值。
所以可以交换 main 中的 a 和 b。
🔹3. 引用传递 mySwap03
void mySwap03(int& a, int& b)
a 和 b 是原变量的“别名”(引用),函数内部直接操作原变量。
既没有创建副本,也没有解引用,语法更清晰,效率更高。
推荐使用。
- 引用的本质
- 本质:引用的本质在c++内部实现是一个指针常量.
**int& ref=a 是创建一个引用,也就是创建了一个a的别名。相当于 Int& const ref=a,ref的指向不能改,而可以通过改a或改ref来改变a的值。 **
讲解示例:
//发现是引用,转换为 int* const ref = &a;
void func(int& ref){
ref = 100; // ref是引用,转换为*ref = 100
}
int main(){
int a = 10;
//自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改
int& ref = a;
ref = 20; //内部发现ref是引用,自动帮我们转换为: *ref = 20;
cout << "a:" << a << endl;
cout << "ref:" << ref << endl;
func(a);
return 0;
}
- 常量引用
作用:常量引用主要用来修饰形参,防止误操作
在函数形参列表中,可以加const修饰形参,防止形参改变实参(指针指向的值不可改变)
示例:
//引用使用的场景,通常用来修饰形参
void showValue(const int& v) {
//v += 10;
cout << v << endl;
}
int main() {
//int& ref = 10; 引用本身需要一个合法的内存空间,因此这行错误
//加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp;
const int& ref = 10;
//ref = 100; //加入const后不可以修改变量
cout << ref << endl;
//函数中利用常量引用防止误操作修改实参
int a = 10;
showValue(a);
system("pause");
return 0;
}
对象模型和this指针
只有非静态变量才属于类内的对象,占对象空间
class Person {
public:
Person() {
mA = 0;
}
//非静态成员变量占对象空间
int mA;
//静态成员变量不占对象空间
static int mB;
//函数也不占对象空间,所有函数共享一个函数实例
void func() {
cout << "mA:" << this->mA << endl;
}
//静态成员函数也不占对象空间
static void sfunc() {
}
};
this指针
C++中成员变量和成员函数是分开存储的
每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码
一块代码是如何区分那个对象调用自己的呢
- this 的基本作用
(1) 区分成员变量和局部变量
当成员变量和函数参数(或局部变量)同名时,this 可以明确指定访问的是 当前对象的成员变量。
例子:Phone 类(数码产品手机)
class Phone {
private:
string brand; // 手机品牌
int price; // 价格(元)
public:
// 构造函数(参数名和成员变量同名)
Phone(string brand, int price) {
this->brand = brand; // this->brand 表示类的成员变量
this->price = price; // this->price 表示类的成员变量
}
void display() {
cout << "Brand: " << this->brand << ", Price: " << this->price << endl;
}
};
int main() {
Phone iphone("Apple", 9999);
iphone.display(); // 输出:Brand: Apple, Price: 9999
return 0;
}
说明:
this->brand 和 this->price 明确指向 Phone 类的成员变量。
如果不加 this,编译器可能会混淆 brand 和 price 是参数还是成员变量。
(2) 返回当前对象(用于链式调用)
this 可以返回当前对象的引用,常用于 链式调用(连续调用多个方法)。
例子:SmartWatch 类(智能手表)
class SmartWatch {
private:
int stepCount; // 步数
int heartRate; // 心率
public:
SmartWatch() : stepCount(0), heartRate(0) {}
// 返回 this 的引用,支持链式调用
SmartWatch& setSteps(int steps) {
this->stepCount = steps;
return *this; // 返回当前对象
}
SmartWatch& setHeartRate(int rate) {
this->heartRate = rate;
return *this; // 返回当前对象
}
void display() {
cout << "Steps: " << this->stepCount << ", Heart Rate: " << this->heartRate << endl;
}
};
int main() {
SmartWatch watch;
watch.setSteps(5000).setHeartRate(80); // 链式调用
watch.display(); // 输出:Steps: 5000, Heart Rate: 80
return 0;
}
说明:
return *this 返回当前对象的引用,使得 setSteps() 和 setHeartRate() 可以连续调用。
- this 的高级用法
(3) 在成员函数中传递当前对象
有时候需要把当前对象作为参数传递给其他函数。
例子:Camera 类(数码相机)
class Camera {
private:
string model;
public:
Camera(string model) : model(model) {}
// 模拟保存相机数据到数据库
void saveToDatabase() {
DatabaseManager::save(*this); // 把当前对象传给数据库管理器
}
string getModel() {
return this->model;
}
};
class DatabaseManager {
public:
static void save(Camera& cam) {
cout << "Saving camera: " << cam.getModel() << endl;
}
};
int main() {
Camera sony("Sony Alpha A7");
sony.saveToDatabase(); // 输出:Saving camera: Sony Alpha A7
return 0;
}
说明:
DatabaseManager::save(*this) 把当前 Camera 对象传递给数据库管理类。
浙公网安备 33010602011771号