zoukankan      html  css  js  c++  java
  • c++ 副本构造器

    我们都知道两个指针指向同一个变量时如果一个指针被释放那么另一个就会出问题

    为了说明问题我做了一个很恶心的小例子

    class C
    {
    public :
        C(int v)
        {
            ptrInt=new int;
            *ptrInt=v;
    
            valueInt = v;
        }
    
        ~C()
        {
    
        }
        void DelIntV()
        {
            valueInt=0;
            delete ptrInt;
        }
        
        C(const C& c)
        {
    
        }
        int * ptrInt;
        int valueInt;
    private:
        
    };
    
    
    int main()
    {
        C c1(2);
        C c2(3);
        c2=c1;
        std::cout<<"ptrInt "<<c2.ptrInt<<"  value "<<*c2.ptrInt<<std::endl;
        std::cout<<"valueInt "<<c2.valueInt<<std::endl;
        c1.DelIntV();
    
        std::cout<<"address  "<<c2.ptrInt<<"  value "<<*c2.ptrInt<<std::endl;
        std::cout<<"valueInt "<<c2.valueInt<<std::endl;
        std::cin.get();
        return 0;
    }

    这是把c1赋值给了c2后把指针ptrInt的值输出和valueInt输出,再把c1的指针给delete,valueInt赋值为0

    再输出c2的ptrInt和valueInt就会发现指针有问题,看一下输出结果:

    已经不对了吧。

    为了解决这样的问题我第一个想到的就是重载操作符=

    C& operator=(const C &c)
        {
            if(this!=&c)
            {
                delete ptrInt;
                ptrInt = new int;
                *ptrInt= *c.ptrInt;
                valueInt=c.valueInt;
            }
            return *this;
        }

    完整代码

    class C
    {
    public :
        C(int v)
        {
            ptrInt=new int;
            *ptrInt=v;
    
            valueInt = v;
        }
    
        ~C()
        {
    
        }
        void DelIntV()
        {
            valueInt=0;
            delete ptrInt;
        }
        
        C(const C& c)
        {
    
        }
        int * ptrInt;
        int valueInt;
    
        C& operator=(const C &c)
        {
            if(this!=&c)
            {
                delete ptrInt;
                ptrInt = new int;
                *ptrInt= *c.ptrInt;
                valueInt=c.valueInt;
            }
            return *this;
        }
    private:
        
    };
    
    
    int main()
    {
        C c1(2);
        C c2(3);
        c2=c1;
        std::cout<<"ptrInt "<<c2.ptrInt<<"  value "<<*c2.ptrInt<<std::endl;
        std::cout<<"valueInt "<<c2.valueInt<<std::endl;
        c1.DelIntV();
    
        std::cout<<"address  "<<c2.ptrInt<<"  value "<<*c2.ptrInt<<std::endl;
        std::cout<<"valueInt "<<c2.valueInt<<std::endl;
        std::cin.get();
        return 0;
    }

    再看一下输出结果:

    这下就正确了吧,但是如果 我们在main函数里做一个修改

    int main()
    {
        C c1(2);
        C c2=c1;//这里直接赋值
        std::cout<<"ptrInt "<<c2.ptrInt<<"  value "<<*c2.ptrInt<<std::endl;
        std::cout<<"valueInt "<<c2.valueInt<<std::endl;
        c1.DelIntV();
    
        std::cout<<"address  "<<c2.ptrInt<<"  value "<<*c2.ptrInt<<std::endl;
        std::cout<<"valueInt "<<c2.valueInt<<std::endl;
        std::cin.get();
        return 0;
    }

    这样后错误就又和之前一样了,为什么呢,

    编译器将在c类里找一个副本构造器(copy constructor)如果找不到它会自己创建一个,

    即使我们对操作符=进行了重载也没有用,由编译器自己创建的副本构造器仍会以"逐们复制"

    的方式把c1赋值给c2

    这样我们还要重新实现这个副本构造器,

    className(const className &cn);

    我是这样做的

        C(const C& c)
        {
            *this=c;
        }

    这里的=其实就是调用的重载的=方法

    完整代码

    class C
    {
    public :
        C(int v)
        {
            ptrInt=new int;
            *ptrInt=v;
    
            valueInt = v;
        }
    
        ~C()
        {
    
        }
        void DelIntV()
        {
            valueInt=0;
            delete ptrInt;
        }
        
        C(const C& c)
        {
            *this=c;
        }
        int * ptrInt;
        int valueInt;
    
        C& operator=(const C &c)
        {
            if(this!=&c)
            {
                delete ptrInt;
                ptrInt = new int;
                *ptrInt= *c.ptrInt;
                valueInt=c.valueInt;
            }
            return *this;
        }
    
        
    private:
        
    };
    
    
    int main()
    {
        C c1(2);
        C c2=c1;//这里直接赋值
        std::cout<<"ptrInt "<<c2.ptrInt<<"  value "<<*c2.ptrInt<<std::endl;
        std::cout<<"valueInt "<<c2.valueInt<<std::endl;
        c1.DelIntV();
    
        std::cout<<"address  "<<c2.ptrInt<<"  value "<<*c2.ptrInt<<std::endl;
        std::cout<<"valueInt "<<c2.valueInt<<std::endl;
        std::cin.get();
        return 0;
    }

    结果

  • 相关阅读:
    IOptions、IOptionsMonitor、IOptionsSnapshot的区别
    基于 .NET 的 FluentValidation 验证教程
    挂载NFS网络文件系统教程
    gcc简要知识点
    二叉树遍历(前序、中序、后序、层次、广度优先、深度优先遍历)
    项目管理的一些知识总结
    Vue从零开发单页应用程序项目
    CRC校验原理
    Linux 文件搜索神器 find 实战详解
    Linux 三剑客之 grep、sed、awk 使用详解
  • 原文地址:https://www.cnblogs.com/li-peng/p/3776384.html
Copyright © 2011-2022 走看看