views:

157

answers:

3

I have defined the following class:

class Action
{
    public: 
    Action(){ _bAllDone = false; }

    void AddMove( Move & m );
    private:
        std::deque<Move> _todo;
        bool _bAllDone;
};

The member AddMove is defined as follows:

void Action::AddMove( Move & m )
{ 
    _todo.push_back( m ); 
}

I noted that without the reference argument to this function the Copy Constructor was called twice, whereeas with a reference argument it was called only once. Is calling a Copy Constructor only once instead of twice a good reason to use a reference argument?

+17  A: 

The deque class in STL is supposed to maintain a copy of the element you pass to its push_back method. That is where one copy constructor comes from.

If you get rid of the reference in addMove(), you will first get a copy of the parameter (and thus one invocation of the copy constructor), and then when you push back, you will get a second copy.

The dual invocation of the copy constructor is wasteful so the reference is preferable. However, you should declare the parameter of addMove() as a const reference, to indicate to the caller that the element will not be modified. Under such an assurance (assuming you don't break it), it is safe to pass the object by reference without worrying and without paying the penalty of an object copy.

Uri
A fine answer, and +1 for passing it as const.
Stuart Thompson
GRB
+4  A: 

Seems like a big advantage to me. Things could get very slow if you are performing many adds iteratively. The actual amount of work would depend on the definition of Move and its copy constructor. And small changes could have severe effects on performance. Bite either way, passing by copy would still be twice as much work.

The overall effect of this will depend on how much of the entire processing is spend on this operation. Do it once, you'll never notice; do it a few thousand times, and it may be significant. However as a general principle, avoid copying data where you can safely reference it, especially since in this case there is no particular clarity or complexity issue - it is as easy to make it fast as it is to make it slow, so why would you make it slow?

Clifford
I think this is a great point.
Uri
A: 

It must be a reference, otherwise you'll be incurring an unnecessary (and potentially incorrect) copy of the argument. It should also be const, otherwise you'll unnecessarily restrict your callers.

Note also that names with a leading underscore are reserved to the language implementation, so your program is actualy "undefined".

HTH

dcw