• C++拷贝对象


    简介

    对象的创建中,常常有这样的需求,就是把对象复制一份。
    而复制有三种方法:

    1.通过初始化来复制

    例如:Object o1(10); Object o2=o1;

    2.通过赋值来复制

    例如:Object o1(10); Object o2; o2=o1;

    3.通过默认拷贝函数来复制

    例如:Object o1(10); Object o2(o1);

    实际上,第一种方法内部原理是执行了第三种的拷贝函数,默认的拷贝函数是浅拷贝,也就是说只能对基本类型数值进行拷贝

    Object类如下:

    class Object
    {
        private:
            int _num;
        public:
            Object(int num)
            {
                _num=num;
            }
    
    };

    分析

    第一种复制对象方法原理(初始化复制)

    1.首先 Object o2=o1 这句是先执行了o1的默认拷贝函数

    此处o1的默认拷贝函数申明为: Object(const Object& obj),该实现体为编译器默认的浅复制方法实现,因此对于含有复杂变量的类,需要重写该函数

    2.然后执行o1的拷贝函数后返回一个匿名对象

    3.最后将该匿名对象命名为o2

    1

    第二种复制方法原理(赋值复制)

    *该原理较为简单,就是直接将简单基本变量值拷贝一份赋值给拷贝对象
    2

    第三种复制方法原理(拷贝函数复制)

    *第一种原理已解释


    实例

    代码

    Object.h

    class Object
    {
        private:
            int _num;
        public:
            Object(int num)
            {
                _num=num;
            }
    
            int getNum()
            {
                return _num;
            }
    
    };

    main.cpp

    #include <iostream>
    #include "Object.h"
    using namespace std;
    
    int main(int argc, char** argv) {
    
        Object o1(10);
        Object o2=o1;
        cout<<o2.getNum()<<endl;
    
        Object oo1(20);
        Object oo2(10);
        oo2=oo1;
        cout<<oo2.getNum()<<endl;
    
        Object ooo1(30);
        Object ooo2(ooo1);
        cout<<ooo2.getNum()<<endl;
    
        return 0;
    }

    运行结果

    3


    提升

    代码

    Object.h

    #ifndef OBJECT_H
    #define OBJECT_H
    
    #include <stdlib.h>
    #include <string.h>
    
    class Object
    {
        private:
            char *_name;
        public:
            Object(char *name)
            {
                _name=(char*)malloc(sizeof(char)*(strlen(name)+1));
                strcpy(_name,name);
            }
    
    
    };
    
    #endif

    main.cpp

    #include <iostream>
    #include "Object.h"
    using namespace std;
    
    void Test()
    {
        Object o1("test");
        Object o2(o1);
    }
    
    
    int main(int argc, char** argv) {
    
        Test();
        return 0;
    }

    *这段代码在较为严格的编译器中会报错,这是因为默认拷贝函数是浅拷贝,对基本的值进行拷贝
    *然而o2拷贝o1的值时,拷贝的是_name的值,在栈中也就是字符串的地址值,因此拷贝后的o2的_name只是引用了o1的_name指向的字符串
    *因此在Test函数结束时,首先o2被析构,其_name指向的字符串被回收。然后o1被析构,其_name指向的字符已在o2析构时被回收,因此o1的_name是野指针,因此产生错误。

    4

    改进代码

    Object.h

    #ifndef OBJECT_H
    #define OBJECT_H
    
    #include <stdlib.h>
    #include <string.h>
    
    class Object
    {
        private:
            char *_name;
            int _num;
        public:
            Object(int num,char *name)
            {
                _num=num;
                _name=(char*)malloc(sizeof(char)*(strlen(name)+1));
                strcpy(_name,name);
            }
    
            Object(const Object& obj)
            {
                _name=(char*)malloc((sizeof(char)*strlen(obj._name)+1));
                strcpy(_name,obj._name);
            }
    
    };
    
    #endif
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 数字黑洞
    Minifilter微过滤框架:框架介绍以及驱动层和应用层的通讯
  • 原文地址:https://www.cnblogs.com/pwc1996/p/5957865.html
Copyright © 2020-2023  润新知