c++ 副本构造器

简介: 我们都知道两个指针指向同一个变量时如果一个指针被释放那么另一个就会出问题 为了说明问题我做了一个很恶心的小例子 class C { public : C(int v) { ptrInt=new int; *ptrInt=v; ...

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

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

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;
}

结果

 

 

 

目录
相关文章
|
Java C++
C++类中在构造器中调用本类的另外构造器
C++类中在构造器中调用本类的另外构造器
97 0
|
C++
C++异常处理与临时副本
首先以一个简单的程序开头如下: #include using namespace std; void test(int& a,int& b) {         int c;         if(a==b)         {            ...
870 0
|
19天前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
21 4
|
19天前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
18 4
|
18天前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
17 1
|
28天前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)
|
28天前
|
编译器 C++
【C++类和对象(中)】—— 我与C++的不解之缘(四)
【C++类和对象(中)】—— 我与C++的不解之缘(四)
|
30天前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
51 1