拷贝构造函数调用时机

1、用已知的函数初始化新的对象

2、参数以值的形式传递

3、函数存在返回值(函数以值的形式返回)//函数以引用的形式返回不调用

#include<iostream>
#include<vector>
using namespace std;
class person {
    int age;
public:
    person() {
        cout << "调用无参构造函数" << endl;
    }
    person(int age) {
        this->age = age;
        cout << age << endl;
    }
    person(const person& other) {//加const保护参数
        this->age = other.age;
        cout << "调用拷贝构造函数" << endl;
    }//拷贝函数使用引用的原因:避免拷贝函数被无限递归
    ~person() {
        cout << "调用解析函数" << endl;
    }
};
void fun(person other) {//参数以值的形式传递的时候,调用拷贝构造

}
person fun() {
    person p;
    return p;
}
void test01() {
    person p;
    person p1 = p;//隐式函数调用拷贝构造函数
    person p2;
    p2 = p;//无法调用拷贝构造函数
}
void test02(){
    person p;
    fun(p);
}
void test03() {
    fun();
}
void test04() {
    person p4 = fun();//调用拷贝构造,但是被编译器优化掉了一次
}
int main() {
    test03();
    cout << "____________" << endl;
    return 0;
}

浅拷贝:

两个对象里面的指针成员变量指向同一个堆区内存

class person {
    int age;
 int *p;
public:
    person() {
        cout << "调用无参构造函数" << endl;
    }
    person(int age) {
        this->age = age;
        cout << age << endl;
                  p=new int[age];  
    }
    person(const person& other) {
        this->age = other.age;
                  this->p=p;//都指向同一个堆区,所以在释放的时候,一块堆区内存会被释放两次,造成堆区内存的重复释放                 
                  cout << "调用拷贝构造函数" << endl;
    }
    ~person() {
        cout << "调用解析函数" << endl;
    }
};
int main(){
    person p(3);
    person p1=p;
}

深拷贝:(有指针变量,并且指向同一个内存的情况下,使用)

两个对象里面的指针成员变量,各自创建一块新的堆区内存(大小内容相同),以此来避免堆区被非法访问的情况

class person {
    int age;
 int *p;
public:
    person() {
        cout << "调用无参构造函数" << endl;
    }
    person(int age) {
        this->age = age;
        cout << age << endl;
                  p=new int[age];  
    }
    person(const person& other) {
        this->age = other.age;
                 this ->p=new int[age];//创建新的堆区内存,避免了两个指针指向同一块堆区的情况出现 
                 //保证大小一样
                 //保证内容一样
                 for(int i=0;i<age;i++){
                     this->p[i]=other.p[i];                 
                 }             
                  cout << "调用拷贝构造函数" << endl;
    }
    ~person() {
        cout << "调用解析函数" << endl;
    }
};
int main(){
    person p(3);
    person p1=p;
}

总结

#include<bits/stdc++.h>
using namespace std;

/*
什么是拷贝(复制)构造函数?
    用已经存在的对象拷贝新的对象


拷贝构造函数在什么时候被调用?
    用已经存在的对象拷贝新的对象

    当对象以值的形式作为函数参数
    当对象以值的形式作为函数的返回值

深拷贝和浅拷贝有什么区别?
    浅拷贝就是简单的赋值操作,会造成同一块堆区内存被释放两次
    成员变量有指针的时候使用深拷贝,深拷贝会重新申请一块堆区内存解决了同一块内存被释放两次的错误
*/
class A
{
    int n;
    int *p;
public:
    A() 
    {
        p = nullptr;
    }
    A(int n)
    {
        this->n = n;
        p = new int(n);
    }
    A(const A& other)
    {
        //编译器提供默认拷贝构造为浅拷贝
    /*    this->n = other.n;
        this->p = other.p;*/

        //自己实现的深拷贝
        this->n = other.n;
        if(other.p )this->p = new int(*other.p); //如果没走if this->p为野指针,所以加上else
        else this->p = nullptr; //此时排除野指针
        cout << "拷贝构造";
    }
    ~A()
    {
        if (p) delete p;
    }
};

void fun(A a)//当对象以值的形式作为函数参数
{

}
int main()
{
    A a;
    //函数在被调用的时候才会开辟函数栈,函数栈中存放的是函数的参数和函数的局部变量
    fun(a);

    //A a(3);
    //A b(a); //括号法  调用拷贝构造

    //A c = a; //隐士转换的方式调用构造函数
    //A d = A(a); // 显示调用
    return 0;
}

class A
{
    int n;
    int *p;
public:
    A() 
    {
        p = nullptr;
    }
    A(int n)
    {
        this->n = n;
        p = new int(n);
    }
    A(const A& other)
    {
        //编译器提供默认拷贝构造为浅拷贝
    /*    this->n = other.n;
        this->p = other.p;*/

        //自己实现的深拷贝
        this->n = other.n;
        if(other.p )this->p = new int(*other.p); //如果没走if this->p为野指针,所以加上else
        else this->p = nullptr; //此时排除野指针
        cout << "拷贝构造";
    }
    ~A()
 {    
        if (p) delete p;
    }
};

void fun(A a)//当对象以值的形式作为函数参数
{

}
int main()
{
    A a;
    //函数在被调用的时候才会开辟函数栈,函数栈中存放的是函数的参数和函数的局部变量
    fun(a);

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值