Sign in to follow this  
Grain

Explicit Copy member function.

Recommended Posts

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;        
    } 
};

Share this post


Link to post
Share on other sites
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& )

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this