I recently reviewed copy constructor, assignment operator, copy swap instance seen here: What is the copy and swap idiom? and many other places -
The link above is a great post, but I still had a few questions - A lot of places answer these questions, on stackoverflow and many other sites, but I have not seen much consistency -
1 - If you have try
- catch
around areas where we allocate new memory for deep copy in copy constructor? (Ive seen it both ways)
2 - Regarding inheritance for both the copy constructor and the assignment operator, when should the base class functions be called and when should these functions be virtual?
3 - Is std::copy
best way to duplicate memory in the copy constructor? I saw this with memcpy
, and I saw others say memcpy
worst thing on earth.
Consider the example below (thanks for all the reviews), this raised additional questions:
4 - Should we check self-appointment? If so, where
5 - a question with a question, but I saw a replacement used as: std::copy(Other.Data,Other.Data + size,Data);
it should be: std::copy(Other.Data,Other.Data + (size-1),Data);
if swap goes from "First to Last" and the 0th element is Other.Data?
6 - Why does the constructor with comments not work (I needed to resize for mysize)? Suppose this means that regardless of the order that I write to them, the constructor will always call the distribution element first?
7 - Any other comments on my implementation? I know the code is useless, but I'm just trying to illustrate the point.
class TBar { public: //Swap Function void swap(TBar &One, TBar &Two) { std::swap(One.b,Two.b); std::swap(One.a,Two.a); } int a; int *b; TBar& operator=(TBar Other) { swap(Other,*this); return (*this); } TBar() : a(0), b(new int) {} //We Always Allocate the int TBar(TBar const &Other) : a(Other.a), b(new int) { std::copy(Other.b,Other.b,b); *b = 22; //Just to have something } virtual ~TBar() { delete b;} }; class TSuperFoo : public TBar { public: int* Data; int size; //Swap Function for copy swap void swap (TSuperFoo &One, TSuperFoo &Two) { std::swap(static_cast<TBar&>(One),static_cast<TBar&>(Two)); std::swap(One.Data,Two.Data); std::swap(One.size,Two.size); } //Default Constructor TSuperFoo(int mysize = 5) : TBar(), size(mysize), Data(new int[mysize]) {} //TSuperFoo(int mysize = 5) : TBar(), size(mysize), Data(new int[size]) {} *1 //Copy Constructor TSuperFoo(TSuperFoo const &Other) : TBar(Other), size(Other.size), Data(new int[Other.size]) // I need [Other.size]! not sizw { std::copy(Other.Data,Other.Data + size,Data); // Should this be (size-1) if std::copy is First -> Last? *2 } //Assignment Operator TSuperFoo& operator=(TSuperFoo Other) { swap(Other,(*this)); return (*this); } ~TSuperFoo() { delete[] Data;} };