CERT.OOP.COPY_MUTATES

Copy operations must not mutate the source object.

Vulnerability and risk

Copy operations (copy constructors and copy assignment operators) are expected to copy the salient properties of a source object into the destination object, with the resulting object being a "copy" of the original. What is considered to be a salient property of the type is type-dependent, but for types that expose comparison or equality operators, includes any properties used for those comparison operations. This expectation leads to assumptions in code that a copy operation results in a destination object with a value representation that is equivalent to the source object value representation. Violation of this basic assumption can lead to unexpected behavior.

Mitigation and prevention

When implementing a copy operator, do not mutate any externally observable members of the source object operand or globally accessible information. Externally observable members include, but are not limited to, members that participate in comparison or equality operations, members whose values are exposed via public APIs, and global variables.

Example

Copy
  #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;               //uncompliant code
   }
 
   A& operator=(const A &other) {
     if (&other != this) {
       m = other.m;
       other.m = 0;              //uncompliant code
     }
     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);
 }