[C++]拷贝构造函数 copy constructor

使用场景

拷贝构造函数是用另一个对象构造当前对象的时候执行的。

拷贝构造函数就是函数名是当前类的名字,参数为当前类的另一个对象的函数

编译器合成的拷贝构造函数

如果你没有定义拷贝构造函数,编译器会替你合成一个。

绝大多数情况下,使用编译器合成的版本即可。

除非需要手动进行复制控制

自己定义拷贝构造函数

class Student
{
public:
    //拷贝构造函数就是函数名是当前类的名字,参数为当前类的另一个对象的函数
    Student(const Student& copy_from);//声明拷贝构造函数
    string m_name;
    int m_age;
};

//定义拷贝构造函数
Student::Student(const Student& copy_from)
 :m_name(copy_from.m_name),m_age(copy_from.m_age)
{
}

有了上面自定义的拷贝构造函数,当再次发生对象拷贝构造的时候就会执行上面的拷贝构造函数(虽然在大多数时候你都不必大费周折亲自写这样一个函数,使用编译器合成的版本即可)。

何时执行拷贝构造函数

有下面三种情况:

1 用已有对象构造新对象的时候

Student stu;//先定义一个对象
Student stu2(stu);//(1)会调用拷贝构造函数
Student stu3=stu ;//(2)会调用拷贝构造函数,这里和(1)是一样的,仅仅是写法不同而已

如果对象已经被创建,会调用赋值操作符而不是复制构造函数:

Student stu;

Student stu2;//在这里被创建

stu2 = stu;//这里调用赋值操作符重载(见后文)

完整示例代码1:

#include <iostream>//cin cout
using namespace std;

class Student
{
public:
    //规则1:如果类的用户自己定义了构造函数
    // ,编译器就不会自动合成类的默认构造函数Student(void)
    //这样类就不存在默认构造函数了

    //类的用户自己定义了拷贝构造函数(拷贝构造函数也算是一个构造函数)
    //按照规则1,此时类不再拥有Student(void)这个函数
    Student(const Student& from)
    {
        cout << "copy constructor called." << endl;
    }

    //由于上面已经定义了一个构造函数,按照规则1,
    //Student stu;这条语句就会因为类不存在默认构造函数而编译报错
    //为了能够让我们可以写Student stu;这条语句来创建对象
    // ,我们在这里显示定义类的默认构造函数
    Student(void)
    {
        cout << "default constructor called." << endl;
    }
};

int main(int argv, char* argc[])
{
    cout << "flag1" << endl;//打印标记信息,用来查看函数执行的顺序
    Student stu;//先定义一个对象
    cout << "flag2" << endl;//打印标记信息,用来查看函数执行的顺序
    Student stu2(stu);//(1)会调用拷贝构造函数
    cout << "flag3" << endl;//打印标记信息,用来查看函数执行的顺序
    Student stu3 = stu;//(2)会调用拷贝构造函数,这里和(1)是一样的,仅仅是写法不同而已
    cout << "flag4" << endl;//打印标记信息,用来查看函数执行的顺序

    return 0;
}

2 给函数传递值类型参数的时候

void test_function(Student s)
{//s在该函数被调用的时候创建,该函数执行完之后释放
    s.m_name = "李四";//修改s的名字
}
int main()
{
    Student stu("张三");
    test_function(stu);//(1)创建stu的副本,函数内使用副本
    cout<<stu.m_name;//还是输出“张三”,因为修改的是,函数内的副本
}

参考:向函数传递参数

完整示例代码2:

#include <iostream>//cin cout
#include <string>
using namespace std;

class Student
{
public:
    Student(const Student& from)//拷贝构造函数
    {
        cout << "copy constructor called." << endl;
    }
    //如果只提供上面的拷贝构造函数,编译器就不再生成默认构造函数
    //,会而导致类对象就不可以直接创建,所以还需要提供一个默认构造函数
    Student(void)
    {
        cout << "default constructor called." << endl;
    }
    Student(const string& name) :m_name(name)
    {
        cout << "string constructor called." << endl;
    }
    string m_name;//存放学生姓名
};
void test_function(Student s)
{//s在该函数被调用的时候创建,该函数执行完之后释放
    cout << "flag2" << endl;
    s.m_name = "李四";//修改s的名字
    cout << "flag3" << endl;
}//s释放的时刻
int main()
{
    cout << "flag0" << endl;
    Student stu("张三");
    cout << "flag1" << endl;
    test_function(stu);//(1)创建stu的副本,函数内使用副本
    cout << "flag4" << endl;
    cout << stu.m_name;//还是输出“张三”,因为修改的是,函数内的副本
}

3 函数返回值类型对象的时候

Student get_copy(void)
{
    Student s;
    return s;//这里以s为参数构造构造一个副本,并返回副本,这里发生了拷贝
}

完整示例代码3:

#include <iostream>//cin cout
#include <string>
using namespace std;

class Student
{
public:
    Student(const Student& from)//拷贝构造函数
    {
        cout << "copy constructor called." << endl;
    }
    //如果只提供上面的拷贝构造函数,编译器就不再生成默认构造函数
    //,会而导致类对象就不可以直接创建,所以还需要提供一个默认构造函数
    Student(void)
    {
        cout << "default constructor called." << endl;
    }
};
Student test_function(void)
{//s在该函数被调用的时候创建,该函数执行完之后释放
    cout << "flag2" << endl;
    Student stu;
    cout << "flag3" << endl;
    return stu;
}//s释放的时刻
int main()
{
    cout << "flag1" << endl;
    test_function();//(1)创建stu的副本,函数内使用副本
    cout << "flag4" << endl;
}

拷贝对象发生了什么

1 先构造对象:分配内存空间

2 对应成员赋值:拷贝数据

C++精简教程 目录(必读)

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FL1768317420

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值