C++ 函数传参三种方式详解与 struct/class 核心区别

Ada
Ada
发布时间:2026-10-15| 4人浏览过
原创

C++ 中的结构与类在语法形式上相似,但在默认访问权限和继承行为上存在关键差异;同时掌握值传递、引用传递和指针传递这三种函数调用方式,能有效避免数据意外修改并提升程序运行效率。

结构体基础与函数调用方式

结构体(struct)是一种用户自定义的数据类型,它既可以包含成员变量,也可以定义成员函数。在 C++ 中,对结构体成员的修改进程涉及不同的数据交换机制,直接决定了实参是否会被改变。

首先定义一个用于演示的结构体:

struct Student {
    int number;      // 成员变量:学号
    char name[100];  // 成员变量:姓名
    void num() {     // 成员函数
        number++;
    }
};

第1步:理解传值调用(Value Passing)

目的:观察形参与实参是否共享内存空间,验证数据的独立性。

void func(Student temp) {
    temp.number = 2000;
    strcpy_s(temp.name, sizeof(temp.name), "lisi");
    // 此时 temp 是 student 的副本,内存地址已发生改变

当调用 func(student) 时,系统会创建一个临时的形参对象 temp,并将实参 student 的所有成员值拷贝给 temp。通过调试器可以观察到:student 的地址(如 0x00d7fd20)与函数内部 temp 的地址(如 0x00d7fbe4)完全不同。

调用前实参 student 的地址

进入函数后,形参 temp 拥有独立的地址

结论:由于进行了完整的内存内容拷贝,这种方式的效率较低,特别是当结构体体积较大时,开销显著。且在函数内修改 temp 不会影响外部的 student。

第2步:掌握引用调用(Reference Passing)

目的:利用别名机制,在不拷贝数据的情况下直接操作原对象,兼顾安全与效率。

void func1(Student &temp1) {
    temp1.number = 2000;
    strcpy_s(temp1.name, sizeof(temp1.name), "lisi");
    // 形参 temp1 只是实参 student 的一个别名

调用 func1(student) 时,不会创建新的副本。通过监视可以看到,函数内部的形参 temp1 与外部的实参 student 共享同一个内存地址(如均为 0x00d7fd20)。

调用前实参 student 的地址

函数内部形参 temp1 保持与实参一致

结论:C++ 推荐首选这种方式。它省略了数值拷贝过程,效率极高,且能直接修改外部对象的值。

第3步:分析指针调用(Pointer Passing)

目的:通过存储内存地址来传递对象,实现传统 C 语言风格的修改。

void func2(Student *temp2) {
    temp2->number = 2000;
    strcpy_s(temp2->name, sizeof(temp2->name), "lisi");
    // 通过解引用来操作指向的目标

调用时传入实参的地址 &student。函数接收的是该地址的值(如 0x003af858),并在内部通过箭头操作符修改其所指向的内容。

调用前实参 student 的地址

函数内部指针变量 temp2 记录目标地址

结论:虽然有效避免了拷贝,但由于需要处理指针运算和解引用,不如引用调用直观。在 C++ 开发习惯中,通常更倾向于使用引用。

权限修饰符与类的基本概念

“类”(class)同样为用户自定义数据类型,但其引入了严格的封装概念。理解访问控制是区分结构体与类的核心。

  • public(公有):任何地方均可访问。通常作为对外提供功能的接口。
  • private(私有):仅允许类/结构体内的成员函数访问。从外部无法直接获取或修改。

以教师信息为例,将敏感属性设为私有:

struct Teacher {
public:
    int number;
    char name[100];
    void num() {
        number++;  
        age = 30;  // 内部成员函数可以合法访问私有变量
    }
private:
    int age;       // 外界无法直接调用 teacher.age
};

int main2() {
    Teacher teacher;
    teacher.number = 1001; // OK: 公有成员可直接赋值
}

Struct 与 Class 的本质区别

虽然 class 和 struct 几乎可以实现相同的功能,但它们在两个关键维度上存在默认行为的不同。

1. 默认访问控制权限

这是两者最核心的差异:

  • Struct:所有未明确指定修饰符的成员,默认访问级别为 public。
  • Class:所有未明确指定修饰符的成员,默认访问级别为 private。

注意:如果在使用类或结构体时显式声明了所有的访问属性(即全部写明了 public: 或 private:),那么在这种特定情况下,两者的行为是一致的。

2. 默认继承方式

在进行面向对象编程的多重继承时,这也至关重要:

  • Struct:默认采用 public 继承,父类的 public 成员在子类中依然公开。
  • Class:默认采用 private 继承,父类的公共成员在子类中变为私有。

建议:为了降低维护难度,养成显式指定继承属性的习惯(如 class Child : public Parent)。

类的工程化组织与总结

在实际工程项目中,为了避免重复编译和维护混乱,应当遵循模块化标准。

文件分离规范:

  • 头文件 (.h):存放类的定义、成员声明以及函数原型。例如 student.h,其中只包含数据结构和方法签名。
  • 源文件 (.cpp):存放具体的函数实现逻辑。例如 student.cpp,通过引入对应的 .h 文件来编写函数体。

标准的头文件与源文件分离示意图

综上所述,C++ 提供了灵活的数据抽象手段。开发者应优先使用 class 并利用私有属性保护数据,在非必要不使用指针的场景下(尤其是大型对象传参时),充分利用引用传递的特性来提升效率与可读性。

以上就是 C++ 函数调用与 Struct 和 Class 区别的详细内容,更多关于 C++ 基础架构设计优化资料的关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。