...
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" |
...