vinit
vinit

Reputation: 521

Why is copy constructor not called here?

I'm on a fast track C++ revision course. Trying to brush up some basic concepts. When I run the below program, I see two issues : 1. Copy CC is not called for some reason. 2. Program is crashing for some reason after the function testCC() exits.

Any help is appreciated !

class A
{
public:
    A() 
    {
        this->ptr = new int[10];
    }
    ~A()
    {
        delete[] ptr;
    }
    A(const A &obj)
    {
        std::cout << "Copy CC called\n";
        for (int i = 0; i < 10; i++)
        {
            ptr[i] = obj.ptr[i];
        }
    }
    void set()
    {
        for (int i = 0; i < 10; i++)
        {
            ptr[i] = rand() % 10;
        }
    }
    void print()
    {
        for (int i = 0; i < 10; i++)
        {
            std::cout << ptr[i] << " ";
        }
        std::cout << "\n";
    }
private:
    int *ptr;

};

void testCC()
{
    A a1,a2;
    a1.set();
    std::cout << "Contents of a1\n";
    a1.print();
    a2 = a1;
    std::cout << "Contents of a2\n";
    a2.print();
}

Upvotes: 2

Views: 848

Answers (5)

Karan Shah
Karan Shah

Reputation: 1992

This will not call copy constructor because it is a constructor and should be called while creating the object and a2 is already created.

Possible reason of crash may be that after testCC, when destructor is called, a1's destructor will free the pointer, but since a2's pointer is also.pointing to the same location, while deleting it in the destructor, it will crash.

So always construct object before copying anything.

Upvotes: 0

user93353
user93353

Reputation: 14039

a2 = a1;

is assignment not copy.

A a3 = a1;

This will call the copy constructor.

Write an assignment operator

A & operator=(const A & obj)
{
    std::cout << "Assingment called\n";
    for (int i = 0; i < 10; i++)
    {
        ptr[i] = obj.ptr[i];
    }

    return *this;
}

This will be called by

a2 = a1;

Upvotes: 1

gmbeard
gmbeard

Reputation: 704

a2 = a1 calls the copy assignment operator, not the copy constructor. Your class doesn't implement a copy assignment operator so the compiler generates a default one which just performs a member-wise copy. After a1 = a2 you have two copies of ptr pointing to the same memory, which both a and b try to delete when testCC returns. This double delete is causing the crash.

You can test your copy constructor by writing A a2(a1) or A a2 = a1

Upvotes: 2

Peter Ruderman
Peter Ruderman

Reputation: 12485

The problem, I believe is this line:

a2 = a1;

This line does not invoke A's copy constructor because a2 already exists. (It isn't being constructed at this point.) Instead, it invokes A's assignment operator: A& operator=(const A&)

Since you haven't defined an assignment operator, you get the default compiler generated one which just does a bitwise copy. As a result, a2 and a1 both wind up containing the same ptr value. That's also why your program crashes. When testCC exits, both a1 and a2 are destroyed and both try to free the same array.

Upvotes: 4

cdhowie
cdhowie

Reputation: 168988

Copy-assignment and copy-construction are not the same thing.

a2 = a1 is calling a2.operator=(a1) (copy assignment), not the copy constructor. You can define the copy-assignment operator like this, within the A class:

A & operator=(A const & obj)
{
    // Perform copy...

    return *this;
}

And either way, your copy constructor is bad (you don't initialize ptr before using it) so even if your copy constructor were being used, you would be invoking undefined behavior and probably crash.

Upvotes: 4

Related Questions