brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.1 KiB · 07c4b33 Raw
131 lines · plain
1.. title:: clang-tidy - bugprone-unhandled-self-assignment2 3bugprone-unhandled-self-assignment4==================================5 6`cert-oop54-cpp` redirects here as an alias for this check. For the CERT alias,7the `WarnOnlyIfThisHasSuspiciousField` option is set to `false`.8 9Finds user-defined copy assignment operators which do not protect the code10against self-assignment either by checking self-assignment explicitly or11using the copy-and-swap or the copy-and-move method.12 13By default, this check searches only those classes which have any pointer or C14array field to avoid false positives. In case of a pointer or a C array, it's15likely that self-copy assignment breaks the object if the copy assignment16operator was not written with care.17 18See also:19`OOP54-CPP. Gracefully handle self-copy assignment20<https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP54-CPP.+Gracefully+handle+self-copy+assignment>`_21 22A copy assignment operator must prevent that self-copy assignment ruins the23object state. A typical use case is when the class has a pointer field24and the copy assignment operator first releases the pointed object and25then tries to assign it:26 27.. code-block:: c++28 29  class T {30  int* p;31 32  public:33    T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}34    ~T() { delete p; }35 36    // ...37 38    T& operator=(const T &rhs) {39      delete p;40      p = new int(*rhs.p);41      return *this;42    }43  };44 45There are two common C++ patterns to avoid this problem. The first is46the self-assignment check:47 48.. code-block:: c++49 50  class T {51  int* p;52 53  public:54    T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}55    ~T() { delete p; }56 57    // ...58 59    T& operator=(const T &rhs) {60      if(this == &rhs)61        return *this;62 63      delete p;64      p = new int(*rhs.p);65      return *this;66    }67  };68 69The second one is the copy-and-swap method when we create a temporary copy70(using the copy constructor) and then swap this temporary object with ``this``:71 72.. code-block:: c++73 74  class T {75  int* p;76 77  public:78    T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}79    ~T() { delete p; }80 81    // ...82 83    void swap(T &rhs) {84      using std::swap;85      swap(p, rhs.p);86    }87 88    T& operator=(const T &rhs) {89      T(rhs).swap(*this);90      return *this;91    }92  };93 94There is a third pattern which is less common. Let's call it the copy-and-move95method when we create a temporary copy (using the copy constructor) and then move96this temporary object into ``this`` (needs a move assignment operator):97 98.. code-block:: c++99 100  class T {101  int* p;102 103  public:104    T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}105    ~T() { delete p; }106 107    // ...108 109    T& operator=(const T &rhs) {110      T t = rhs;111      *this = std::move(t);112      return *this;113    }114 115    T& operator=(T &&rhs) {116      p = rhs.p;117      rhs.p = nullptr;118      return *this;119    }120  };121 122Options123-------124 125.. option:: WarnOnlyIfThisHasSuspiciousField126 127  When `true`, the check will warn only if the container class of the copy128  assignment operator has any suspicious fields (pointer, C array and C++ smart129  pointer).130  This option is set to `true` by default.131