copy constructor issues with vector class
Hey there. Newbie c++ student here. I am experiment with copy constructors and STL containers. I made a test class A and gave it an assignment operator and a copy constructor. I then instantiated an object of type A and then a vector to hold objects of this class A. Then I used push_back method to insert an instance of A and I get an error in Visual C++ 2010 that breaks to the push_back implementation in vector.cpp.
Code:
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
A();
A(int a, int b);
~A();
A(const A& src);
A operator= (const A &rhs);
private:
int a;
int * b;
};
A::A()
{
a = 0;
b = nullptr;
cout << endl << "A 0 argument constructor called";
}
A::A(int a, int b)
{
this->a = a;
this->b = new int;
*this->b = b;
cout << endl << "A 2 argument constructor called";
}
A::~A()
{
a = 0;
delete b;
cout << endl << "A destructor called";
}
//There is a problem with this copy constructor
A::A(const A& src)
{
this->a = src.a;
this->b = new int;
*this->b = *src.b;
cout << endl << "A copy constructor called";
}
A A::operator= (const A &rhs)
{
A tempA(rhs.a, *rhs.b);
return tempA;
}
int main()
{
A a1(1, 2);
A a2;
vector <A> v1;
v1.push_back(a1);
v1.push_back(a2);
system("pause");
return 0;
}
Object a1 adds just fine into the vector v1, but a2 does not. The problem seems to be with the fact that it was instantiated with my provided 0 argument constructor which assigns the pointer member to nullptr. Here is the output before the debugger breaks:
"
A 2 argument constructor called
A 0 argument constructor called
A copy constructor called
A copy constructor called
A destructor called
"
Now. when I change the default constructor A::A() to assign a memory using "new int" and assign a value to the int, then it adds just fine to the vector and the following output is produced:
"
A 2 argument constructor called
A 0 argument constructor called
A copy constructor called
A copy constructor called
A destructor called
A copy constructor called
"
Something is going on with the pointer in A::A() and I cannot figure out what it is after having read through some copy pointer tutorials. Your debugging help is appreciated. Knowing whats wrong will deeply improve my knowledge of C++
Re: copy constructor issues with vector class
The problem can be seen with a simpler code snippet:
And your copy constructor:
Code:
A::A(const A& src)
{
this->a = src.a;
this->b = new int;
*this->b = *src.b; // Problem on this line
cout << endl << "A copy constructor called";
}
On the line indicated above, what is the value of src.b that you
are de-referencing ?
Re: copy constructor issues with vector class
The problem is with the default constructor. You are assigning null to a pointer
but in your copy constructor you are dereferencing the pointer without checking whether it is null.
In the default constructor, changing b assignment to
Code:
b = new int;
*b = 0;
causes the program to execute without reporting an error.
If you want to be able to assign a null to b, then in every class function that uses b you will need to test b for null before any dereferencing.
Re: copy constructor issues with vector class
You also have a problem with operator =. Operator= usually returns a reference so that multiple assignments work (eg a1 = a2 = a3 = a4;) Therefore you can't return a value which is temp (like tempA) as it no longer exists once the function returns.
Assuming that b is never null (ie set as per my post #3), operator = could be implemented as
Code:
A& A::operator= (const A &rhs)
{
this->a = rhs.a;
*this->b = *rhs.b;
cout << endl << "An assignment called";
return *this;
}
with the class definition changed accordingly. new is not needed here as this->b is already set from a previous constructor.
Re: copy constructor issues with vector class
Quote:
Originally Posted by
bigc++
Hey there. Newbie c++ student here. I am experiment with copy constructors and STL containers.
Your issue has nothing to do with STL containers. Copying and assigning objects correctly can be done without any containers whatsoever, as Philip shows in his code.
All the STL containers do is make copies. But any C++ that makes copies would see the same issue, so it isn't an STL issue. For example, if you pass that faulty object by value to a function, you get the same issues:
Code:
void SomeFunction(A theA)
{
}
int main()
{
A myA;
SomeFunction(myA);
}
There is no STL here, but you get the same issues occuring due to pass-by-value incurring a copy.
Secondly this:
Quote:
A 2 argument constructor called
A 0 argument constructor called
A copy constructor called
A copy constructor called
A destructor called
"
Now. when I change the default constructor A::A() to assign a memory using "new int" and assign a value to the int, then it adds just fine to the vector and the following output is produced:
"
A 2 argument constructor called
A 0 argument constructor called
A copy constructor called
A copy constructor called
A destructor called
A copy constructor called
"
Relying on when or where a copy constructor is called by printing messages will just confuse you. The reason why is that the compiler can make 5, 10, 20, or 1,000 copies if it wants to, or 0 copies if it is able to. The end result of the copies (or non-copying) must be certain, but the number of copies is up to the compiler, compiler options, optimizations, etc.. So don't look at two sets of output and say "this output is different than the other output, so something is right/wrong here".
What you need to do is do as Philip did, and that is to create a simple program that tests copying and assignment.
Code:
int main()
{
A a1;
A a2(a1);
A a3;
a3 = a1;
}
Something like the above. The above tests construction, copy construction, assignment, and destruction using 3 objects. If A allocates memory and/or uses pointers, you can easily test/correct your issues with something like this code.
Regards,
Paul McKenzie
Re: copy constructor issues with vector class
Thanks to all who replied. Insightful answers. It makes sense now
Re: copy constructor issues with vector class
Quote:
Originally Posted by
bigc++
Newbie c++ student here.
As C++ is often taught it's easy to get the impression that writing copy constructors, copy assignment operators and even destructors is very central to C++ programming. It's not. One can in fact argue that these constructs preferrably should be avoided alltogether, especially if you're using the object oriented programming style in general high-level applications. So once you've passed the exam the best you can do is to forget about them. Quite a relief isn't it. :)