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

特殊情况下拷贝构造函数的调用方式及代码示例解析

拷贝构造函数的调用场景(含你的代码分析)

嘿,咱们来拆解你这个问题——先从你的代码入手,再拓展到拷贝构造函数的特殊调用情况~

首先先把你的代码整理成可编译的完整版本(补全必要的头文件):

#include <iostream>
#include <string>
using namespace std;

class Person {
public:
    Person() { cout << "constructor" << endl; };
    Person(istream& a);
    Person(const Person& a) : name(a.name), address(a.address) { 
        cout << "copy constructor" << endl; 
    }
    ~Person() { cout << "destructor" << endl; };
private:
    string name;
    string address;
};

Person::Person(istream& a) {
    a >> name >> address;
    cout << "call constructor with istream" << endl;
}

int main() {
    Person a = Person(cin);
    return 0;
}

你的代码里的拷贝构造调用情况

你写的Person a = Person(cin);,理论上会触发两步:

  1. 调用Person(istream&)构造一个临时的Person对象;
  2. 调用拷贝构造函数,把这个临时对象拷贝给a。

但你在VS2017里运行可能看不到copy constructor的输出——这是因为编译器做了返回值优化(RVO,Return Value Optimization),直接跳过临时对象的创建,在a的内存空间里直接构造对象,所以拷贝构造函数被省略了。

如果想看到拷贝构造被调用,可以关闭VS的优化选项:

  • 右键项目 → 属性 → C/C++ → 优化 → 选择禁用优化(/Od),再运行就能看到拷贝构造的输出了。

拷贝构造函数的其他特殊调用场景

除了上面这种被优化的情况,还有这些场景一定会(或可能)触发拷贝构造:

  • 用已有对象初始化新对象:比如Person b(a);或者Person b = a;(后者和你的代码不同,这里是用已存在的a初始化b,不是临时对象)
  • 函数以值传递方式接收对象参数:比如定义void func(Person p),调用func(a)时,会把a拷贝给形参p,触发拷贝构造
  • 函数返回对象(未被优化时):比如Person createPerson() { return Person(); },如果编译器没做RVO,返回时会拷贝临时对象到调用方
  • 对象被插入到容器中:比如vector<Person> vec; vec.push_back(a);,会把a拷贝到容器的内存空间里
  • 用对象初始化智能指针的指向对象(某些情况):比如shared_ptr<Person> sp(new Person(a));,这里会拷贝a构造新对象

内容的提问来源于stack exchange,提问作者Miralan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:29:04