Explicit Copy member function.

Started by
5 comments, last by NotAYakk 17 years, 6 months ago
Which is the preferred way? My classes sometimes contain pointers to other classes.
class foo
{
    bar* MyBar;
    bar2* MyOtherBar;
public:
    //This
    void copy(const foo& _foo)
    {
        MyBar = new bar(_foo.MyBar); 
        MyOtherBar = new bar2(_foo.MyBar);       
    }

    // OR
    foo copy()
    {
        foo tempFoo;
        tempFoo->MyBar = new bar(MyBar); 
        tempFoo->MyOtherBar = new bar2(MyBar);
        return tempFoo;        
    } 
};

Advertisement
Preferred way is a copy constructor and operator=() overload, which you can use to make natural assignments.

class foo{    bar* MyBar;    bar2* MyOtherBar;public:    foo(const foo& _foo)    :           MyBar(new bar(_foo.MyBar)),           MyOtherBar(new bar2(_foo.MyBar) )    {        }    foo &operator=( const foo& _foo )    {           /*           release previous bar pointers           */           delete MyBar;           delete MyOtherBar;            MyBar = new bar(_foo.MyBar);           MyOtherBar = new bar2(_foo.MyBar);      }    // implement destructor and other constructors};


So we can now just use assignments or intialisation:

foo one;
foo two = one; // foo( const foo& )
foo three;
three = two; // foo &foo::operator=( const foo& )
The safest way to implement raw copying is to implement a copy-constructor and a (preferably no-fail) swap function and implement the copy-assignment operator in terms of the former:
class foo{	public:		foo()			:			my_bar(new int(7))		{		}		foo(foo const & f)			:			my_bar(new int(*f.my_bar))		{		}		~foo()		{			delete my_bar;		}		foo & operator=(foo const & f)		{			foo(f).swap(*this);			return *this;		}	private:		void swap(foo & f)		{			std::swap(my_bar, f.my_bar);		}		int * my_bar;};

Of course, it's even better to avoid raw copying entirely whenever possible and use RAII wrappers instead, like std::vector instead of new[]ed arrays, etc.

Σnigma
I prefer to disable operator= and copy-construction by default on any class with a non-trivial constructor.

Make private unimplemented operator= and copy constructors.

If I must have an operator= and copy constructor, I try to use smart pointers that make the problem mostly go away.

Only write copy constructors and operator= as a last resort. They have more problems than most people realize.
Oops. I forgot to mention that I will need to copy derived classes to base class pointers, which is why I cant use a copy constructor or = operator.
Quote:Original post by Grain
Oops. I forgot to mention that I will need to copy derived classes to base class pointers, which is why I cant use a copy constructor or = operator.


Then you want this. (Or, if the base class pointer in question is in turn a member of some other object, this.)
Sketchy, but I hope you get the drift:

template<typename T>struct ClonerSmartPtr {  T* data;  operator T*() { return data; }  T* operator->() {return data;}  T& operator*() {return *data;}  ClonerSmartPtr<T>& operator=(T* other) {    other->clone(&data);    return *this;  }};


Now, do you copy references or do you clone?

If you copy references, you need reference counting at the very least.

If you clone references, then you don't want to have to do it manually -- you want a clone pattern.

In either case, doing the code manually is a bad idea. Mistakes are far too easy. So use SmartPtrs (reference counting, auto-cloning, or whatever) instead of raw pointers and decide on your policy by which ones you pick.

All of a sudden the trivial operator= and copy constructor works, because the data storage describes the data copying policy at the same time.

This topic is closed to new replies.

Advertisement