C++中值传递时触发拷贝构造函数的完整过程

 更新时间:2025年12月26日 15:42:26   作者:挖矿大亨  
本文详细介绍了C++中值传递时触发拷贝构造函数的完整过程,包括触发拷贝构造的时机、过程本质以及如何避免触发拷贝构造,感兴趣的朋友跟随小编一起看看吧

当函数的参数是类的对象(而非指针/引用)时,调用函数传递参数的过程就是值传递,此时编译器会自动调用拷贝构造函数,创建一个实参的“副本”作为函数的形参。

一、值传递触发拷贝构造函数的完整过程

可以把这个过程想象成“复制粘贴”
1、你准备把一个已存在的对象(实参)传给函数
2、因为是值传递,函数不会直接使用原对象,而是需要一个"独立的副本"
3、编译器会调用该类的拷贝构造函数,用原对象(实参)为模板,创建一个新的对象(形参);
4、函数内部操作的是这个“副本”,函数执行完毕后,副本会被销毁(调用析构函数)
5、原对象不受函数内操作的影响

二、代码示例

#include <iostream>
#include <string>
using namespace std;
class Person {
public:
    string name;
    // 带参构造函数
    Person(string n) : name(n) {
        cout << "[构造] 创建对象:" << name << endl;
    }
    // 拷贝构造函数(核心:值传递时会调用)
    Person(const Person& other) {
        this->name = other.name + "(副本)"; // 给副本加标记,方便识别
        cout << "[拷贝构造] 为值传递创建副本:" << this->name << endl;
    }
    // 析构函数
    ~Person() {
        cout << "[析构] 销毁对象:" << name << endl;
    }
    // 成员函数:修改名字(仅影响副本)
    void changeName(string newName) {
        this->name = newName;
        cout << "[函数内] 修改副本名字为:" << this->name << endl;
    }
};
// 函数参数为值传递(Person对象,而非指针/引用)
void testValuePass(Person p) {
    p.changeName("修改后的副本");
}
int main() {
    // 1. 创建原对象
    Person p1("原对象-张三");
    cout << "------------------------" << endl;
    // 2. 调用函数,值传递参数 → 触发拷贝构造
    testValuePass(p1);
    cout << "------------------------" << endl;
    // 3. 查看原对象:未被修改
    cout << "[主函数] 原对象名字:" << p1.name << endl;
    return 0;
}
控制台
[构造] 创建对象:原对象-张三
------------------------
[拷贝构造] 为值传递创建副本:原对象-张三(副本)
[函数内] 修改副本名字为:修改后的副本
[析构] 销毁对象:修改后的副本
------------------------
[主函数] 原对象名字:原对象-张三
[析构] 销毁对象:原对象-张三

三、关键细节拆解

1、触发时机
执行testValuePass(p1)时,编译器发现参数是值传递(Person p),立即调用Person(const Person& other);
拷贝构造函数的参数other就是原对象p1,函数内创建的p是p1的副本。
2、为什么必须是拷贝构造?
如果没有显式定义拷贝构造函数,编译器会生成默认的浅拷贝构造函数,依然会触发(只是没有日志输出);
只有参数是const 类名&的构造函数,才是拷贝构造函数,这是 C++ 的语法规则。
3、对比:避免拷贝构造的方式
如果不想触发拷贝构造(提升性能,避免深拷贝开销),可以把参数改成引用传递

// 引用传递:直接操作原对象,不触发拷贝构造
void testRefPass(Person& p) {
    p.changeName("修改原对象");
}
调用testRefPass(p1)时,不会调用拷贝构造函数,函数内修改的是原对象p1。

四、常见误区澄清

×误区:“值传递只是把对象的值复制过去,和拷贝构造无关”;
√正解:C++ 中,类对象的 “值复制” 本质就是通过拷贝构造函数完成的,这是面向对象的核心规则。

五、总结

1、触发条件:函数参数为类对象(值传递)时,编译器会自动调用拷贝构造函数,创建实参的副本作为形参。
2、过程本质:值传递的 “复制” = 拷贝构造函数的调用 + 新对象(副本)的创建。
3、优化建议:如果不需要修改原对象,用const 类名&(const 引用)传递参数,既不触发拷贝构造,又能防止函数内修改原对象。

到此这篇关于C++中值传递时触发拷贝构造函数的完整过程的文章就介绍到这了,更多相关c++值传递触发拷贝构造函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于C语言 const 和 define 区别

    关于C语言 const 和 define 区别

    这篇文章主要介绍了关于C语言 const 和 define 区别 的相关资料,需要的朋友可以参考下面文章内容
    2021-09-09
  • ros项目调试:vscode下配置开发ROS项目的详细教程

    ros项目调试:vscode下配置开发ROS项目的详细教程

    这篇文章主要介绍了ros项目调试:vscode下配置开发ROS项目,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Java C++题解leetcode1598文件夹操作日志搜集器

    Java C++题解leetcode1598文件夹操作日志搜集器

    这篇文章主要为大家介绍了Java C++题解leetcode1598文件夹操作日志搜集器示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • C语言函数指针的老生常谈

    C语言函数指针的老生常谈

    这篇文章主要为大家介绍了vue组件通信的几种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11
  • c语言描述回文数的三种算法

    c语言描述回文数的三种算法

    这篇文章主要介绍了c语言描述回文数的三种算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • C++ 三种继承方式及好处示例详解

    C++ 三种继承方式及好处示例详解

    这篇文章主要为大家介绍了C++ 三种继承方式及好处示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 你知道C语言函数调用常用的2种方式吗

    你知道C语言函数调用常用的2种方式吗

    本篇博客会讲解C语言函数调用的2种方式,分别是:传值调用和传址调用。这2种函数调用方式有什么区别呢?为什么会有不同的效果呢?分别有哪些用途呢?下面就来一一展开
    2023-04-04
  • C++ Boost MultiIndex使用详细介绍

    C++ Boost MultiIndex使用详细介绍

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C语言动态内存管理深入探讨

    C语言动态内存管理深入探讨

    动态内存是相对静态内存而言的。所谓动态和静态就是指内存的分配方式。动态内存是指在堆上分配的内存,而静态内存是指在栈上分配的内存,本文带你深入探究C语言中动态内存的管理
    2022-06-06
  • 浅谈CMake配置OpenCV 时静态链接与动态链接的选择

    浅谈CMake配置OpenCV 时静态链接与动态链接的选择

    下面小编就为大家带来一篇浅谈CMake配置OpenCV 时静态链接与动态链接的选择。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01

最新评论