...
Non-Compliant Code Example
| Code Block | ||
|---|---|---|
| ||
class Widget {
// ...
};
class Thingy {
public:
// ...
Thingy& operator=(const Thingy& rhs);
// ...
private:
Widget *w;
};
// ...
Thingy& Thingy::operator=(const Thingy& rhs) {
delete w; // delete the current Widget
w = new Widget(*rhs.w); // create a copy of rhs's Widget
return *this;
}
// ...
|
...
Better is to test for self-assignment, and to carry out the work of the assignment only in the case that it is not a self-assignment.
| Code Block | ||
|---|---|---|
| ||
Thingy& Thingy::operator=(const Thingy& rhs) {
if (this != &rhs) {
delete w;
w = new Widget(*rhs.w);
}
return *this;
}
|
...
Alternatively, a copy to the original resource can be taken and not deleted until the new value has been established:
| Code Block | ||
|---|---|---|
| ||
Thingy& Thingy::operator=(const Thingy& rhs) {
Widget *original = w;
w = new Widget(*rhs.w);
delete original;
return *this;
}
|
...
Alternatively, a resource managing smart pointer (or other resource managing container) may be used to hold the external resource:
| Code Block | ||
|---|---|---|
| ||
class Thingy {
public:
// ...
// compiler-generated copy assignment now correct
private:
std::tr1::shared_ptr<Widget> w;
};
|
...
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
RES36 MEM42-C CPP | 1 (low) | 2 (probable) | 1 (high) | P2 | L3 |
...