Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is Copy-and-swap idiom too slow in assignment operator?

41 views
Skip to first unread message

JiiPee

unread,
Oct 22, 2022, 2:55:21 AM10/22/22
to
In a class when defining an assignment operator:

operator=(const Obj& other)

, if one uses the Copy-and-swap idiom to copy @other to this:

Obj copy(other);
copy.swap(*this);

, this is obviously really good looking and elegant etc. But just
wondering how much slower it would be than a straight/old (not so
elegant/risky):

this->a = other.a;
this->b = other.b;
...

? I was just checking, if doing swap(), then needs to make 2 or 3 times
more copy operations in total complare to old way for simple data types
(int, float, double, bool...). If one has many of these, then is it
gonna be much slower?

Or... is the compiler gonna optimize out these extra integer/double copy
operations?

Andrey Tarasevich

unread,
Oct 22, 2022, 5:17:12 AM10/22/22
to
On 10/21/2022 11:55 PM, JiiPee wrote:
> In a class when defining an assignment operator:
>
> operator=(const Obj& other)
>
> , if one uses the Copy-and-swap idiom to copy @other to this:
>
> Obj copy(other);
> copy.swap(*this);
>
> , this is obviously really good looking and elegant etc. But just
> wondering how much slower it would be than a straight/old (not so
> elegant/risky):
>
> this->a = other.a;
> this->b = other.b;
> ...

With what kind of class? What is `a` and `b`?

If this is a flat class, then of course straightforward copying will be
faster, since it requires only one copying, while copy-and-swap will
copy the same data twice (or even thrice). The larger the class - the
slower in comparison the copy-and-swap is going to be.

If this is a "deep" class that handles resources, which need to be
copied, then in general case expenses spent on releasing the old
resources and cloning new ones in copy constructor or assignment
operator will dwarf the overhead brought in by swapping.

--
Best regards,
Andrey.

Sam

unread,
Oct 22, 2022, 7:50:53 AM10/22/22
to
JiiPee writes:

> In a class when defining an assignment operator:
>
> operator=(const Obj& other)
>
> , if one uses the Copy-and-swap idiom to copy @other to this:
>
> Obj copy(other);
> copy.swap(*this);
>
> , this is obviously really good looking and elegant etc. But just wondering
> how much slower it would be than a straight/old (not so elegant/risky):
>
> this->a = other.a;
> this->b = other.b;

For a simple class, copy/swap is an overkill. But for a complex class that
contains many objects that also have their own bookkeeping, or their own
special needs, then copy/swap offers a simple way to remove a lot of code
duplication.

For example: if, for whatever reasons, a and b have a deleted assignment
operator, but have functional copy/move semantics.


JiiPee

unread,
Oct 22, 2022, 9:02:30 AM10/22/22
to
On 22/10/2022 14:50, Sam wrote:
> For a simple class, copy/swap is an overkill.

could test how much slower it is. But its simple and elegant. And no
need to then repeat code.

Juha Nieminen

unread,
Oct 24, 2022, 3:10:34 AM10/24/22
to
JiiPee <kerrttuPo...@gmail.com> wrote:
> In a class when defining an assignment operator:
>
> operator=(const Obj& other)
>
> , if one uses the Copy-and-swap idiom to copy @other to this:
>
> Obj copy(other);
> copy.swap(*this);
>
> , this is obviously really good looking and elegant etc. But just
> wondering how much slower it would be than a straight/old (not so
> elegant/risky):
>
> this->a = other.a;
> this->b = other.b;
> ...

It depends on the situation.

For example, suppose you are assigning one (object similar to) std::string
to another: If the target already has enough capacity to contain the
source string, then no new allocations will be needed and it's just
a simple straightforward string copy. If the copy-and-swap idiom had
been used here, a new dynamic memory allocation would have been done
and the existing one would have been deleted, for no good reason.

The difference becomes even more drastic with classes like std::list
(or any class with a similar functionality): If the target already
has elements in it, then assigning can just assign the source elements
onto the existing target elements, thus avoiding unneeded extra
allocations. The copy-and-swap idiom would make dynamic allocations
for every single element to be copied, and then delete the existing
ones, for no reason.

Of course in other situations it doesn't really make much of a
difference.

JiiPee

unread,
Oct 24, 2022, 10:38:50 AM10/24/22
to
On 24/10/2022 10:10, Juha Nieminen wrote:
> It depends on the situation.

good answer. good point. yes not blindly following a given rule.
But, I wonder why on those videos those expects do not mention so much
about this but its like "this is the elegant way to do it"?

Öö Tiib

unread,
Oct 29, 2022, 2:59:31 PM10/29/22
to
It is because swap does not (have conceivable reasons to) throw and
so there are no way that copy and swap trashes the object of this.

OTOH when this->b = other.b; throws then this->a is tricky to return to
what it was. So your straight/old assignment is actually bad/naive
in language with exceptions.
0 new messages