CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  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,721

    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
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    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. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  4. #4
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    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. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

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

    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
  •  





Click Here to Expand Forum to Full Width

Featured