Should I clear() containers passed in as a parameter, or swap in a new object? [closed]

StackOverflow https://stackoverflow.com/questions/10128276

  •  31-05-2021
  •  | 
  •  

Frage

I'm in a discussion at work as to how to properly handle containers as parameters.

We have a function that takes in a container parameter, and wants to return the container filled ONLY with what the function puts into it:

class bar;

void foo(std::vector<bar> &bars) 
{
   //do stuff that fills bars.
   //exceptions may be thrown.
   //we may also legally return early 
   return;
}

On one side of the discussion, we have people that say we should bars.clear() first and then run the function.

For example:

void foo(std::vector<bar> &bars) 
{
   bars.clear();
   //do stuff that fills bars.
   //exceptions may be thrown.
   //we may also legally return early 
   return;
}

My own preference is to try to reach the strong exception guarantee as closely as I can, which means making a local container, filling that and swapping before returning, but otherwise leaving bars untouched.

For example:

void foo(std::vector<bar> &bars) 
{
   std::vector<bar> localBars;
   //do stuff that fills localBars.
   //exceptions may be thrown.
   //we may also legally return early 
   if (returnEarly)
   {
       bars.swap(localBars);
       return;
   }
   //do more stuff that may change localBars

   bars.swap(localBars);
   return;
}

The first example is the 'classic' method; of clearing your parameters before doing anything and going from there.

The second method, to me, sets up a strong exception guarantee (assuming nothing else the function does can change internal states), and avoids a clear() call.

Are there any advantages or disadvantages to picking one method over the other one?

Note that for this function, a strong exception guarantee isn't required; if the function fails nothing in the parameters or anything else it does will matter by the time it gets up to the exception handler.

War es hilfreich?

Lösung

The two are really different.

Advantages of clear:

  • reuse memory
  • no out-dated information left in bars

Advantages of swap:

  • strong exception guarantee

The question cannot be answered in general, what semantics/guarantees do you seek in your case ?

Andere Tipps

You've mentionned one advantage of using swap: it provides a strong exception guarantee. Whether this is really important is another question: if the argument passed by the client will be immediately destructed when the exception propagates (almost always the case in the code I've seen), it really doesn't matter.

There is another important difference: clear() doesn't free memory or reduce the capacity. If the client code calls your function in a loop, with the vector defined outside of the loop, the vector will quickly attain its maximum size, and you will not have any reallocations when filling it. With the swap strategy, of course, you always reallocate. And if you're not concerned with this sort of performance issue, you should be returning the vector, not taking a non-const reference to it as a parameter.

swap() is better with respect to exceptions. clear may have an advantage if the container is huge and you have memory constraints. a more functional/cleaner style can be:

std::vector<bar> void foo()
{
    std::vector<bar> bars;
    ...
    return bars;
}

RVO will take care of it most of the time and with c++11 and move constructors/assignment it will just be efficient.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top