Vector deep copy pointers

I am a very new programmer and a super newbie, so I don’t know too much about C ++. I had a specific question regarding creating deep copies of pointers. I have class A, full POD, and a pointer to this class (A * P). I have a second class B, which contains some other PODs and a vector of pointers to class A. I want to fill this vector of deep copies A * P, because in the loop I will dynamically select and free it. The following work does not work. I consider it my copy constructor and operator overloading =. This is what I do for fun and learning.

class A { public: ..... ..... ..... }; class B { public: B(); ~B(); B(const B &Copier); B& B::operator=(const B &Overloading); vector<A*> My_Container; A* Points_a_lot; int counter; }; B::B() { counter=0; Points_a_lot=NULL; } B::~B() { for(size_t i=0; i<My_Container.size(); i++) { delete My_Container[i]; } } B::B(const B &Overloading) { My_Container[counter]=new A(*Overloading.Points_a_lot); } B& B::operator=(const B &Overloading) { if(!Overloading.My_Container.empty()) { Overloading.My_Container[counter]=new B(*Overloading.Points_a_lot); } return *this; } int main() { A* p=NULL; B Alphabet; for(....) { p=new A; //some stuff example p->Member_of_A=3; etc.. Alphabet.My_Container[Alphabet.counter]=p; Alphabet.counter++; delete p; } return 0; } 

Any help would be great. I thank you for your time. Suppose the list includes the required libraries.

+4
source share
5 answers

I don’t quite understand what your requirements are, so I tried to fix the code and make a deep copy of B , since that is what you seem to be asking about.

 #include <vector> using namespace std; class A { public: A() : m_someInt(0), m_someFloat(0.0f) {} // Redundant but putting it here for you to see when it is called (put break-point) A(const A& a_other) { m_someInt = a_other.m_someInt; m_someFloat = a_other.m_someFloat; } int m_someInt; float m_someFloat; }; class B { public: B(); ~B(); B(const B &Copier); B& B::operator=(const B &Overloading); void Cleanup(); void AddA(const A* a); private: vector<A*> My_Container; A* Points_a_lot; }; B::B() { Points_a_lot=NULL; } B::~B() { Cleanup(); } B::B(const B &Overloading) { // Deep copy B operator=(Overloading); } B& B::operator=(const B &Overloading) { // Delete old A's Cleanup(); // Not using iterators to keep it simple for a beginner for (size_t i = 0; i < Overloading.My_Container.size(); ++i) { // We need new A which will then copy from the A in Overloading container A* newA = new A( *(Overloading.My_Container[i]) ); // Done with allocation and copy, push_back to our container My_Container.push_back(newA); } return *this; } void B::Cleanup() { // Assuming B is not responsible for cleaning up Points_a_lot Points_a_lot = NULL; for (size_t i = 0; i < My_Container.size(); ++i) { delete My_Container[i]; } // Automatically called when My_Container is destroyed, but here we // are open to the possibiliy of Cleanup() being called by the client My_Container.clear(); } void B::AddA(const A* a) { // We are adding a new A. In your code, the incoming A is going to // be destroyed, therefore, we need to allocate a new A and copy // the incoming A A* newA = new A(*a); My_Container.push_back(newA); } int main() { A* p=NULL; B Alphabet; for(int i = 0; i < 10; ++i) { p = new A(); //some stuff example p->Member_of_A=3; etc.. Alphabet.AddA(p); delete p; } // If you put a breakpoint here and step through your code, you will see // `B` deep-copied B NewAlphabet = Alphabet; return 0; } 

A few notes:

  • New ing and delete ing A in a loop is a bad idea. I understand that you are doing this just to learn, which is great, but you can keep that in mind. Instead of destroying A through p , allow B to take responsibility for the new A
  • Go through the code using the debugger to see how it works.
  • Try sending a code that is as close as possible to your original when you ask: "Why does this not work / compile"
+1
source

Well, it seems to me that you are very confused about what the operator should do. Take a look at this page for operator overloading . This should get you started on the right track for this feature.

Secondly, the question that is not related to your question is this question about why your fields (member variables, what-you-you) should be private.

+3
source

There are many errors in the code. The main one is that your assignment operator and copy constructor do not completely copy vector pointers to A in general, you are trying to put a B* in the location of the vector. The assignment operator must do this to remove the elements that the vector points to and fill it with deep copies of the elements that the original vector of the object points to after checking for self-determination. Your copy constructor should be filled with deep copies of the elements of the source objects.

Secondly, you must provide a method that adds elements to the vector of your class, and let it set an internal counter variable. The need to coordinate both the vector and the counter from the outside is error prone, and one of the advantages of OOP is to avoid such an error. But even better, remove the counter variable. You do not need it. Then your main will be simplified:

 int main() { B Alphabet; for(....) { A* p = new A; //some stuff example p->Member_of_A=3; etc.. Alphabet.appendElement(p); // B takes ownership, no need to delete in main } } 

and appendElement may be

 class B { public: void appendElement(A* element) { myContainer_.push_back(element); } // other public methods private: std::vector<A*> myContainer_; }; 

You could further improve all of this by storing some sort of separate smart ownership index instead of raw indexes. This would mean that you don’t have to worry about making exceptions yourself. But this is probably beyond the scope of this question.

Now you should avoid pointers. In this case, you do not need to create copy constructors, assignment operators, or destructors. Synthesized compilers will do everything perfectly. Your class B comes down to

 class B { public: void appendElement(const A& element) { myContainer_.push_back(element); } // other public methods private: std::vector<A> myContainer_; }; 
+2
source

It looks like you should instead consist of unique_ptrs My_Container so that when you assign the vector to acquire ownership of instance A

 for(....) { p=new A; //some stuff example p->Member_of_A=3; etc.. Alphabet.My_Container[Alphabet.counter]=p; Alphabet.counter++; delete p; } 

to instead declare My_Container as

 vector<std::unique_ptr<A*> > My_Container; 

then the code will be

 for(....) { p=new A; //some stuff example p->Member_of_A=3; etc.. Alphabet.My_Container[Alphabet.counter]=p; Alphabet.counter++; } 

then if you need to make a deep copy, create a member in called clone () or something else and return unique_ptr to the instance, use this when you need to create a copy.

0
source

You can take a look at boost::ptr_vector . Its interface is very similar to the std::vector interface, but it is intended for pointers and thus:

  • owns resources (therefore no memory leak)
  • allow polymorphic storage (derived classes)
  • is constant and copied.

For the copy to work, you need to provide an implementation of A* new_clone(A const*) .

0
source

All Articles