Solve self assignment situation in operator= by comparing addresses of source and target objects, careful statement ordering, and copy-and-swap
.
When operator= applies on more than one object, two or more of the objects may be the same:
|
|
This is the result of aliasing (having more than one way to refer to an object). In general, operations on references or pointers to multiple objects of the same type (or objects of different types derived from the same base class) need to consider that the objects might be the same.
When trying to manage resources manually rather than to take advantage of resource-managing objects (item 13, item 14), it is possible to accidentally release a resource before being done using it:
|
|
When *this
(the target of the assignment) and rhs
(the source of the assignment) are the same object, delete
destroys both of them in the begining, resulting to the fact that this
points to a deleted object instead of being unchanged by the assignment to self. Moreover, besides self-assignment-unsafe, this implementation of operator= is also exception-unsafe.
There are three possible ways to solve the problem:
- Identity test at the top (solve self-assignment-unsafe)
- A careful ordering of statements (solve both self-assignment-unsafe and exception-unsafe)
- Copy and swap. (solve both potential unsafe situation)
1. Identity test
|
|
The problem here is that once the new Bitmap
expression yields an exception (due to insufficient memory or Bitmap
’s copy constructor throwing one), this
will end up refer to a deleted Bitmap
, which is toxic for there’s no way to safely delete them or even safely read them.
2. Careful reorder
|
|
Under this implementation, even it new Bitmap
throws an exception, pb
and this
remain unchanged. Moreover, it does work even without the identity test.
Considering efficiency, it may be sensible to put the identity test back at the top. However, considering the frequency of self-assignment situation as well as the longer codes and more branches in the flow of control, it may actually decrease runtime speed (at least the effectiveness of instruction prefetching, caching, and pipelining can be reduced).
3. Copy and swap
This is an alternative way to the above careful reordering technique, which is closely associated with exception safety (item 29).
|
|
A variation taking advantage of the fact that passing by value makes a copy of it (item 20):
|
|
This variation sacrifices the clarity but may let compilers generate more efficient code by moving the copying operation from the body of the function to construction of the parameter.