copy constructor issues with vector class
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7

Thread: copy constructor issues with vector class

  1. #1
    Join Date
    May 2013
    Posts
    10

    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++

  2. #2
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,560

    Re: copy constructor issues with vector class

    The problem can be seen with a simpler code snippet:

    Code:
    A a1;
    A a2(a1);
    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 ?
    Last edited by Philip Nicoletti; May 9th, 2013 at 06:27 AM.

  3. #3
    Join Date
    Dec 2012
    Location
    England
    Posts
    1,994

    Re: copy constructor issues with vector class

    The problem is with the default constructor. You are assigning null to a pointer

    Code:
    b = nullptr;
    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.
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  4. #4
    Join Date
    Dec 2012
    Location
    England
    Posts
    1,994

    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.
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  5. #5
    Join Date
    Apr 1999
    Posts
    27,418

    Re: copy constructor issues with vector class

    Quote Originally Posted by bigc++ View Post
    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:
    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
    Last edited by Paul McKenzie; May 9th, 2013 at 12:17 PM.

  6. #6
    Join Date
    May 2013
    Posts
    10

    Re: copy constructor issues with vector class

    Thanks to all who replied. Insightful answers. It makes sense now

  7. #7
    Join Date
    May 2009
    Posts
    2,413

    Re: copy constructor issues with vector class

    Quote Originally Posted by bigc++ View Post
    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.
    Last edited by nuzzle; May 11th, 2013 at 06:32 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center