You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++拷贝构造函数调用疑问:为何第三种方式未触发显式实现?

关于拷贝构造函数与赋值运算符的疑问

问题详情

我测试了三种涉及对象拷贝的操作:

Test t2 = t1; // 方式1
Test t3(t1);  // 方式2
Test t4;      // 方式3
t4 = t1;

我显式定义的拷贝构造函数会将原对象的每个数据成员加10,前两种方式能正常调用该构造函数并执行加10操作,但第三种方式没有执行加10操作,看起来用了隐式的拷贝逻辑。

测试代码

#include <iostream>
using namespace std ; 
class Test
{
    int m,n ; 
    public: 
    Test() ; 
    Test(int,int) ; 
    ~Test() ; 
    Test(Test&) ; 
    void showData() ; 
} ; 
inline Test::Test(Test& t)
{
    cout<<"called"<<endl ;
    m = t.m + 10 ; 
    n = t.n + 10 ; 
}
inline Test::Test(){}
inline Test::Test(int m,int n)
{
    Test::m = m ; 
    Test::n = n ; 
}
inline Test::~Test(){}
inline void Test::showData()
{
    cout<<m<<" "<<n<<endl ; 
}
int main()
{
    Test t1(3,4) ; 
    t1.showData() ; 
    Test t2(t1) ; 
    t2.showData() ;
    Test t3 = t1 ;
    t3.showData() ;
    Test t4 ; // 调用隐式逻辑
    t4 = t1 ; 
    t4.showData() ;
    return 0 ; 
}

程序输出

3 4
called
13 14
called
13 14
3 4

我已经通过重载赋值运算符解决了第三种方式的问题,但想知道:为什么已经显式定义了拷贝构造函数,第三种方式还是没触发它,反而用了隐式逻辑?


问题解答

核心原因是这两种操作的本质完全不同:

  • 前两种方式属于对象初始化:Test t2(t1)是直接初始化,Test t3 = t1是拷贝初始化,二者都会触发拷贝构造函数,用来创建一个新对象并以已有对象为模板完成初始化,所以会执行你自定义的加10逻辑。
  • 第三种方式是赋值操作:t4 = t1是在t4已经被默认构造函数创建完成后,把t1的值拷贝给t4,这个过程触发的是赋值运算符,而非拷贝构造函数。

C++规则中,只要你没有显式重载赋值运算符,编译器会自动为类生成一个默认赋值运算符,这个默认函数只会做简单的成员逐值拷贝(也就是你观察到的“隐式逻辑”),不会复用拷贝构造函数里的自定义逻辑。

所以哪怕你定义了拷贝构造函数,也不会影响默认赋值运算符的生成和调用,这就是第三种方式没触发你自定义逻辑的根本原因。


内容的提问来源于stack exchange,提问作者M.B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 12:43:36