0

0

C++拷贝构造函数什么时候调用 C++对象复制场景汇总【机制】

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-01-26 13:01:18

|

648人浏览过

|

来源于php中文网

原创

拷贝构造函数仅在四种明确时机被调用:①显式或复制初始化新对象(如A a(b)或A a = b);②值传递参数;③返回局部对象(未被RVO优化时);④抛出或按值捕获异常。

c++拷贝构造函数什么时候调用 c++对象复制场景汇总【机制】

拷贝构造函数被调用的四个明确时机

不是所有赋值都会触发拷贝构造函数。它只在「创建新对象」且「用同类型已有对象初始化」时才调用,本质是构造行为,不是赋值行为。

常见触发场景有且仅有以下四种:

  • 用一个对象显式初始化另一个对象:A obj2(obj1);A obj2 = obj1;(注意:后者是语法糖,仍调用拷贝构造,不是 operator=
  • 函数传值传参:形参为非引用类型,如 void func(A a) { ... },调用时 func(obj) 会以 obj 构造形参 a
  • 函数返回局部对象(且未被编译器优化掉):如 A func() { A tmp; return tmp; },返回时需用 tmp 构造临时返回对象
  • 抛出或捕获异常时,若异常对象类型非引用,也会触发拷贝构造(例如 throw A{}; 后被 catch(A e) 捕获)

为什么 A a = b; 看似赋值却调用拷贝构造?

这是 C++ 的定义问题:A a = b; 是「复制初始化」(copy initialization),语义上等价于 A a(b);,属于构造而非赋值。即使重载了 operator=,这里也不会调用它。

容易混淆的点:

立即学习C++免费学习笔记(深入)”;

  • A a = b; → 调用拷贝构造函数
  • A a; a = b; → 先调用默认构造,再调用 operator=
  • A a(b); → 直接调用拷贝构造函数(最明确写法)

编译器可能对 A a = b; 执行 RVO/NRVO 优化,跳过拷贝构造——但这是优化结果,不是语言规则改变。

BgSub
BgSub

免费的AI图片背景去除工具

下载

哪些情况「不」调用拷贝构造函数?

理解「不调用」比「调用」更能避免误判。以下看似相似,实则绕过拷贝构造:

  • 传引用参数:void f(const A& a)f(obj) 不构造新对象,不调用任何构造函数
  • 返回局部对象但启用 RVO(Return Value Optimization):现代编译器(g++/clang 默认开启)常直接在调用方上构造返回对象,跳过拷贝
  • 使用移动语义(C++11+):当源对象是右值且类定义了移动构造函数,A a = std::move(b); 或返回临时对象时,优先调用移动构造而非拷贝构造
  • 聚合类型(如 plain struct)的 POD 成员复制:若类无用户定义拷贝构造,且满足 trivially copyable 条件,底层可能只是 memcpy,但语言层面仍视为“调用隐式生成的拷贝构造”——这点容易引发调试困惑,需看编译器实际行为

调试时怎么确认拷贝构造是否真的被调用?

最可靠方式是定义带日志的拷贝构造函数,并关闭优化验证:

struct A {
    A() { std::cout << "default\n"; }
    A(const A&) { std::cout << "copy ctor\n"; } // 显式定义
    A(A&&) { std::cout << "move ctor\n"; }
};

然后用 g++ -O0 编译运行,观察输出。注意:

  • -O2 可能消除拷贝(RVO、copy elision),导致日志不出现,不代表逻辑不存在
  • C++17 起,某些 copy elision 变成强制行为(如函数返回临时对象),此时拷贝构造即使存在也禁止调用——但函数仍必须可访问、可调用(否则编译失败)
  • 若类禁用了拷贝(= delete),而代码中意外触发拷贝构造(如传值参数),错误信息会明确提示 use of deleted function 'A::A(const A&)'

真正难排查的是隐式触发 + 优化共存的情况,比如模板函数里传值参数,在不同实例化路径下可能有的走拷贝、有的被优化掉。这时候得结合编译器输出(-fno-elide-constructors 强制禁用 elision)和 AST 查看实际调用链。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

527

2023.09.20

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

176

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

98

2025.11.27

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

395

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

575

2023.08.10

java值传递和引用传递有什么区别
java值传递和引用传递有什么区别

java值传递和引用传递的区别:1、基本数据类型的传递;2、对象的传递;3、修改引用指向的情况。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

108

2024.02.23

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

274

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.12.29

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

14

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号