...
Generally, a copy operation that mutates the source operand is a safe operation to perform only when the source operand is at the end of its lifetime, because the value representation of the source operand is not important. Such a situation is a good candidate for a move operation instead of a copy operation.
Noncompliant Code Example
In this noncompliant code example, the copy operations for A mutate the source operand by resetting its member variable m to 0. When std::fill() is called, the first element copied will have the original value of obj.m, 12, at which point obj.m is set to 0. The subsequent nine copies will all retain the value 0.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <algorithm>
#include <vector>
class A {
mutable int m;
public:
A() : m(0) {}
explicit A(int m) : m(m) {}
A(const A &other) : m(other.m) {
other.m = 0;
}
A& operator=(const A &other) {
if (&other != this) {
m = other.m;
other.m = 0;
}
return *this;
}
int get_m() const { return m; }
};
void f() {
std::vector<A> v{10};
A obj(12);
std::fill(v.begin(), v.end(), obj);
} |
Compliant Solution
In this compliant solution, the copy operations for A no longer mutate the source operand, ensuring that vector contains equivalent copies of obj. Instead, A has been given move operations that perform the mutation when it is safe to do so.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <algorithm>
#include <vector>
class A {
int m;
public:
A() : m(0) {}
explicit A(int m) : m(m) {}
A(const A &other) : m(other.m) {}
A(A &&other) : m(other.m) { other.m = 0; }
A& operator=(const A &other) {
if (&other != this) {
m = other.m;
}
return *this;
}
A& operator=(A &&other) {
m = other.m;
other.m = 0;
return *this;
}
int get_m() const { return m; }
};
void f() {
std::vector<A> v{10};
A obj(12);
std::fill(v.begin(), v.end(), obj);
} |
Risk Assessment
Copy operations that mutate the source operand or global state can lead to unexpected program behavior. In the case of using such a type in a Standard Template Library container or algorithm, this can also lead to undefined behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
OOP58-CPP | Low | Likely | Low | P9 | L2 |
Automated Detection
Tool | Version | Checker | Description |
|---|---|---|---|
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Bibliography
| [ISO/IEC 14882-2014] | Subclause 12.8, "Copying and Moving Class Objects" Table 21, "CopyConstructible Requirements" Table 23, "CopyAssignable Requirements" |
| [ISO/IEC 14882-2003] | |
| [Hinnant 05] | "Rvalue Reference Recommendations for Chapter 20" |
...