简体   繁体   中英

Does the assignment operator call copy constructor?

#include<iostream>
using namespace std;
class test
{
    int *p;
public:
    test(){p=new int(0);}
    test(const test &src)
    {
        p=new int(*src.p);
    }
    ~test(){delete p;}
    void show(){cout<<*p<<" at "<<p<<endl;}
    void setx(int a)
    {
        *p=a;
    }
};
int main()
{
    test a,b;
    a.setx(10);
    a.show();
    b=a;
    b.show();
    test c=a;
    c.show();
}

Here inside main(), test c=a calls the copy constructor and allocates memory for the integer. No problem with that, both cp and ap point to different memory locations. But the line b=a causes bp and ap to point to the same memory location. I have created my own copy constructor, bp and ap should have pointed to different memory locations. What's going on here?

Edit: To be precise, my question is what's the difference between implicitly-defined copy constructor and implicitly-defined copy assignment operator?

b=a; 

Here also bit by bit copy is done (ap and bp pointing to same location), it does not invoke copy constructor because constructor is called when b in defined (default constructor).so you have to overload = operator

test &operator =(const test &src)
{
    *this->p=*src.p;    //copy value not address 

     return *this;
}

Add this to your class test and you need to check the memory is allocated or not by new because new can fail to allocate requested memory.

But here the copy constructor is called

test c=a;

If you really want to use an *int, I'd use smart pointers, to simplify the resource ownership:

class Test
{
public:
    Test(){p=std::shared_ptr<int>(new int(0));}
    Test(const Test &src){p=std::shared_ptr<int>(new int(*(src.p.get())));}
    ~Test()=default;
    Test& operator= (const Test& src) {p = std::make_shared<int>(*(src.p.get())); return *this;}
    void show(){cout<<*(p.get())<<endl;}
    void setx(int a) {*(p.get())=a;}
private:
    std::shared_ptr<int> p;
};

however, it does not make too much sense to use a pointer or smart pointers (obfuscated code) considering that the lifespan of the int is the same than the object itself (so you don't have to dynamically allocate it):

class Test
{
public:
    Test():p(0){}
    Test(const Test &src):p(src.p){}
    ~Test()=default;
    Test& operator= (const Test& src) {p = src.p; return *this;}
    void show(){cout<<p<<endl;}
    void setx(int a) {p=a;}
private:
    int p;
};

You need to define operator=. The copy constructor won't be called for an already-constructed object.

eg,

test&operator=(const test&t)
{
    if(p)delete p;
    p=new int(*t.p);
    return *this;
}

Try this:

test& operator= (const test& anotherTest)
{
    if (this != &anotherTest) 
    { 
        if ( NULL != this->p )
            *(this->p) = *(anotherTest.p);
        else
            this->p = new int (*anotherTest.p)
    }   

    return *this;
}

I dont know why, but if I:

test a;
a.setx(10);
a.show();
test b = a;
b.show();
test c = a;
c.show();

instead of :

test a,b;
a.setx(10);
a.show();
b=a;
b.show();
test c=a;
c.show();

ap and bp point to different addresses

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM