動靜俎合 發表於 2025-12-26 15:42:26

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

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>一、值传递触发拷贝构造函数的完整过程</li><li>二、代码示例</li><li>三、关键细节拆解</li><li>四、常见误区澄清</li><li>五、总结</li></ul></div><p>当函数的参数是类的对象(而非指针/引用)时,调用函数传递参数的过程就是值传递,此时编译器会自动调用拷贝构造函数,创建一个实参的&ldquo;副本&rdquo;作为函数的形参。</p>
<p class="maodian"></p><h2>一、值传递触发拷贝构造函数的完整过程</h2>
<p>可以把这个过程想象成&ldquo;复制粘贴&rdquo;<br />1、你准备把一个已存在的对象(实参)传给函数<br />2、因为是值传递,函数不会直接使用原对象,而是需要一个&quot;独立的副本&quot;<br />3、编译器会调用该类的拷贝构造函数,用原对象(实参)为模板,创建一个新的对象(形参);<br />4、函数内部操作的是这个&ldquo;副本&rdquo;,函数执行完毕后,副本会被销毁(调用析构函数)<br />5、原对象不受函数内操作的影响</p>
<p class="maodian"></p><h2>二、代码示例</h2>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;iostream&gt;
#include &lt;string&gt;
using namespace std;
class Person {
public:
    string name;
    // 带参构造函数
    Person(string n) : name(n) {
      cout &lt;&lt; "[构造] 创建对象:" &lt;&lt; name &lt;&lt; endl;
    }
    // 拷贝构造函数(核心:值传递时会调用)
    Person(const Person&amp; other) {
      this-&gt;name = other.name + "(副本)"; // 给副本加标记,方便识别
      cout &lt;&lt; "[拷贝构造] 为值传递创建副本:" &lt;&lt; this-&gt;name &lt;&lt; endl;
    }
    // 析构函数
    ~Person() {
      cout &lt;&lt; "[析构] 销毁对象:" &lt;&lt; name &lt;&lt; endl;
    }
    // 成员函数:修改名字(仅影响副本)
    void changeName(string newName) {
      this-&gt;name = newName;
      cout &lt;&lt; "[函数内] 修改副本名字为:" &lt;&lt; this-&gt;name &lt;&lt; endl;
    }
};
// 函数参数为值传递(Person对象,而非指针/引用)
void testValuePass(Person p) {
    p.changeName("修改后的副本");
}
int main() {
    // 1. 创建原对象
    Person p1("原对象-张三");
    cout &lt;&lt; "------------------------" &lt;&lt; endl;
    // 2. 调用函数,值传递参数 → 触发拷贝构造
    testValuePass(p1);
    cout &lt;&lt; "------------------------" &lt;&lt; endl;
    // 3. 查看原对象:未被修改
    cout &lt;&lt; "[主函数] 原对象名字:" &lt;&lt; p1.name &lt;&lt; endl;
    return 0;
}
控制台
[构造] 创建对象:原对象-张三
------------------------
[拷贝构造] 为值传递创建副本:原对象-张三(副本)
[函数内] 修改副本名字为:修改后的副本
[析构] 销毁对象:修改后的副本
------------------------
[主函数] 原对象名字:原对象-张三
[析构] 销毁对象:原对象-张三</pre></div>
<p class="maodian"></p><h2>三、关键细节拆解</h2>
<p>1、触发时机<br />执行testValuePass(p1)时,编译器发现参数是值传递(Person p),立即调用Person(const Person&amp; other);<br />拷贝构造函数的参数other就是原对象p1,函数内创建的p是p1的副本。<br />2、为什么必须是拷贝构造?<br />如果没有显式定义拷贝构造函数,编译器会生成默认的浅拷贝构造函数,依然会触发(只是没有日志输出);<br />只有参数是const 类名&amp;的构造函数,才是拷贝构造函数,这是 C++ 的语法规则。<br />3、对比:避免拷贝构造的方式<br />如果不想触发拷贝构造(提升性能,避免深拷贝开销),可以把参数改成引用传递</p>
<div class="jb51code"><pre class="brush:cpp;">// 引用传递:直接操作原对象,不触发拷贝构造
void testRefPass(Person&amp; p) {
    p.changeName("修改原对象");
}
调用testRefPass(p1)时,不会调用拷贝构造函数,函数内修改的是原对象p1。</pre></div>
<p class="maodian"></p><h2>四、常见误区澄清</h2>
<p>&times;误区:&ldquo;值传递只是把对象的值复制过去,和拷贝构造无关&rdquo;;<br />&radic;正解:C++ 中,类对象的 &ldquo;值复制&rdquo; 本质就是通过拷贝构造函数完成的,这是面向对象的核心规则。</p>
<p class="maodian"></p><h2>五、总结</h2>
<p>1、触发条件:函数参数为类对象(值传递)时,编译器会自动调用拷贝构造函数,创建实参的副本作为形参。<br />2、过程本质:值传递的 &ldquo;复制&rdquo; = 拷贝构造函数的调用 + 新对象(副本)的创建。<br />3、优化建议:如果不需要修改原对象,用const 类名&amp;(const 引用)传递参数,既不触发拷贝构造,又能防止函数内修改原对象。</p>
<p>到此这篇关于C++中值传递时触发拷贝构造函数的完整过程的文章就介绍到这了,更多相关c++值传递触发拷贝构造函数内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>C++函数三种传参形式(指针传递、引用传递、值传递)</li><li>C++之值传递&指针传递&引用传递的示例详解</li><li>解析C/C++值传递和址传递的区别</li><li>C++小知识:C/C++中不要按值传递数组</li><li>java及C++中传值传递、引用传递和指针方式的理解</li><li>C++拷贝构造函数和赋值运算符重载详解</li><li>详解C++中构造函数,拷贝构造函数和赋值函数的区别和实现</li><li>详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数</li><li>C++中拷贝构造函数的应用详解</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: C++中值传递时触发拷贝构造函数的完整过程