首页 > 其他分享 >拷贝构造(详解)

拷贝构造(详解)

时间:2024-11-05 22:50:56浏览次数:3  
标签:cout int age 构造 person 详解 拷贝 include

一、拷贝构造函数

拷贝构造函数,就像他的名字一样,使来拷贝的,他的作用是把一个已经存在的对象进行拷贝后,用拷贝来的值进行给其他对象赋值和作为返回值和参数等。

一、拷贝构造函数调用时机

拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:拷贝构造的参数是引用类型

  • 通过使用另一个同类型的对象来初始化新创建的对象。
  • 复制对象把它作为参数传递给函数。
  • 复制对象,并从函数返回这个对象。

下面我们来看一个拷贝构造函数的例子:

#include<iostream>
#include<vector>
#include<string>
using namespace std;
class person {
public:
    int age;
    person() {
    
        cout << "调用无参构造" << endl;
    
    }
    person(int age) {
        this->age = age;
        cout << "调用有参构造" << endl;
    
    
    }
    person(const person&other) {
    
        cout << "调用拷贝构造" << endl;
        this->age = other.age;
    
    }
    ~person() {
    
        cout << "调用析构函数" << endl;
    
    }

};
void fun(person other) {
//参数以值的形式传递的时后掉用拷贝构造,不能是引用

}
person fun() {
    person p;
    return p;
}
void t1() {
    person p;
    person p1 = p;//用已经存在的对象初始化新对象隐式调用
    person p2;
    p2 = p;//不调用拷贝构造,这是赋值过程

}
void t2() {
    person p;
    fun(p);

}
void t3() {
    fun();
}
int main() {
    t3();
    return 0;
}

 二、深拷贝浅拷贝

说到拷贝构造函数就不得不提到深拷贝浅拷贝的概念

深拷贝:对对象进行全面的复制,重新的创建堆区内存,把原对象中的数据复制到新地址中。

浅拷贝:简单的赋值过程,只是将内存的地址赋值给另一个变量,不重新申请内存空间,这样就出现了一个问题,就是在释放内存时会出现同一块内存被释放两次的情况。

地址存储变量1=地址1123析构将内存归还操作系统
内存1123内存1123被释放
地址存储变量2=地址1123此对象析构函数也要调释放内存1123但是此内存已经归还操作系统找不到了,报错

下面我们来看深拷贝和浅拷贝的例子:

浅拷贝 

#include<iostream>
#include<vector>
#include<string>
using namespace std;
class person {
public:
    int age;
    int* p;
    person() {
    
        cout << "调用无参构造" << endl;
        age = 0;
        p = nullptr;

    }
    person(int age) {
        this->age = age;
        this->p = new int[age];
        for (int i = 0;i < age;i++) {
            p[i] = i;
        
        
        }
        cout << "调用有参构造" << endl;
    
    
    }
    person(const person&other) {
    
        cout << "调用拷贝构造" << endl;
        this->age = other.age;
        this->p = other.p;//浅拷贝;两个对象中的成员指针变量指向同一块地址
        //此代码运行会有错误,析构函数会非法访问
    }
    ~person() {
    
        cout << "调用析构函数" << endl;
    
    }

};
void fun(person p) {
//参数以值的形式传递的时后掉用拷贝构造,不能是引用

}
person fun() {
    person p;
    return p;

}
void t1() {
    person p;
    person p1 = p;//隐式调用
    person p2;
    p2 = p;//不调用拷贝构造,这是赋值过程


}
void t2() {

    person p;
    fun(p);//实参初始化形参调用

}
void t3() {

    fun();

}
int main() {
    t3();



    return 0;
}

深拷贝

#include<iostream>
#include<vector>
#include<string>
using namespace std;
class person {
public:
    int age;
    int* p;
    person() {
    
        cout << "调用无参构造" << endl;
        age = 0;
        p = nullptr;

    }
    person(int age) {
        this->age = age;
        this->p = new int[age];
        for (int i = 0;i < age;i++) {
            p[i] = i;
        
        
        }
        cout << "调用有参构造" << endl;
    
    
    }
    person(const person&other) {
    
        cout << "调用拷贝构造" << endl;
        this->age = other.age;
        //深拷贝:指向的内存地址不同但是内容大小相同
        this->p = new int[age];//大小一样
        for (int i = 0;i < age;i++) {//内容一样
            this->p[i] = other.p[i];
        
        
        }
    }
    ~person() {
    
        cout << "调用析构函数" << endl;
    
    }

};
void fun(person p) {
//参数以值的形式传递的时后掉用拷贝构造,不能是引用

}
person fun() {
    person p;
    return p;

}
void t1() {
    person p;
    person p1 = p;//隐式调用
    person p2;
    p2 = p;//不调用拷贝构造,这是赋值过程


}
void t2() {

    person p;
    fun(p);//实参初始化形参调用

}
void t3() {

    fun();

}
int main() {
    t3();



    return 0;
}

标签:cout,int,age,构造,person,详解,拷贝,include
From: https://blog.csdn.net/2301_77891039/article/details/143524835

相关文章

  • 代码随想录算法训练营第十六天|leetcode513.找树左下角的值、leetcode112.路径总和、l
    1leetcode513.找树左下角的值题目链接:513.找树左下角的值-力扣(LeetCode)文章链接:代码随想录视频链接:怎么找二叉树的左下角?递归中又带回溯了,怎么办?|LeetCode:513.找二叉树左下角的值_哔哩哔哩_bilibili思路:就是用一个东西存储result,使用后续遍历,如果遇到了最深的那一个值,就......
  • 【算法】递归+深搜:106.从中序与后序遍历序列构造二叉树(medium)
    目录1、题目链接相似题目:2、题目3、解法函数头-----找出重复子问题函数体---解决子问题4、代码1、题目链接106.从中序与后序遍历序列构造二叉树(LeetCode)相似题目:105.从前序与中序遍历序列构造二叉树889.根据前序和后序遍历构造二叉树(LeetCode)2、题目3、解法......
  • javaWeb详解
    JavaWeb开发是指使用Java编程语言来构建Web应用程序的过程。它涉及到多个技术和框架,旨在帮助开发者创建动态的、交互式的网站。下面是一些JavaWeb开发中常用的技术和概念:1.JavaServletsServlet是运行在Web服务器或应用服务器上的Java程序,用于扩展服务器的功能。它们可以......
  • Docker安装MongoDB详解(mongo.latest)
    一、MongoDB介绍MongoDB是一种基于分布式文件存储的数据库,使用C++语言开发,旨在为Web应用提供可扩展且高性能的数据存储解决方案。作为一种介于关系数据库和非关系数据库之间的技术,MongoDB具有强大的功能和高效的性能,特别适用于处理海量的非结构化数据。MongoDB的核心概念与特......
  • Java内存区域详解(重点)
    运行时数据区域Java虚拟机在执行Java程序的过程中会把它管理的内存划分成若干个不同的数据区域。JDK1.8和之前的版本略有不同,我们这里以JDK1.7和JDK1.8这两个版本为例介绍。JDK1.7:JDK1.8: 线程私有的:程序计数器虚拟机栈本地方法栈线程共享的:堆方法区......
  • LDAP--Jenkins详解笔记
    一、Ldap的结构1.组织角色所有用户都可以登录,但是只有创建时的admin组角色有增删改的权限,相当于是根目录,千万不能删,删了就全没了注意,admin用户是首个超级登录用户(相当于根),需要用配置文件生成,详见:https://www.cnblogs.com/wangyuanguang/p/18189832##注意修改wyg部分为自己自......
  • Java入门十二——static详解(含toString)
    上节课,我们只是微微提到了static,今天我们来具体讲讲static的用法static1.类名.静态成员变量(上篇博客Java入门十一有讲)为了方便大家查看,我把链接放在这里Java入门11——关键字总结+static-CSDN博客2.类名.静态成员方法这里,我们首先创建两个类,分别是java12和demo1,然后调用d......
  • MyBatis 动态 SQL 详解
    动态SQL简介动态SQL是MyBatis的强大特性之一,它允许在XML映射文件内以标签的形式编写动态SQL,完成逻辑判断和动态拼接SQL的功能。动态SQL可以根据用户输入或外部条件动态地构建查询,避免了硬编码查询逻辑,简化了数据库查询的复杂度,同时提高了代码的可读性和维护性。......
  • golang占位符%v、%+v、%#v详解
    目录%v%+v%#v在Go语言中,fmt包提供了格式化字符串的功能,类似于C语言的printf函数。fmt包中的%v、%+v和%#v是用于格式化输出的占位符,它们各自有不同的用途。%v含义:%v表示以默认格式(值)输出变量。对于基本类型如整数、浮点数等,它会直接输出其值;对于结构体,它会输出......
  • C++中类的三的特性是什么?什么是构造函数和析构函数?它们的作用是什么?
    1)C++中类的三大特性是什么?请简要解释。C++中类的三大特性是封装、继承和多态。一、封装封装是将数据和操作数据的方法封装在类中,对外部隐藏类的内部实现细节。通过将数据成员设为私有(private),并提供公有的(public)成员函数来访问和修改这些数据,从而实现对数据的保护和控......