Uploaded image for project: 'Rules Repository'
  1. Rules Repository
  2. RSPEC-5018

Move and swap operations should be "noexcept"

    XMLWordPrintable

    Details

    • Message:
      Ensure that this XXX is exception-free and declare it "noexcept".
    • Highlighting:
      Hide

      move operation name name

      Show
      move operation name name
    • Default Severity:
      Blocker
    • Impact:
      High
    • Likelihood:
      High
    • Default Quality Profiles:
      Sonar way, MISRA C++ 2008 recommended
    • Covered Languages:
      C, C++
    • Remediation Function:
      Constant/Issue
    • Constant Cost:
      2min
    • Analysis Scope:
      Main Sources, Test Sources
    • CppCoreGuidelines:
      C.66, C85

      Description

      Move operations (move constructor, move assignment operator) are all about efficient resource stealing. When stealing resources from the source, you don't have to allocate any memory or perform any other operation that might fail. This is why most people will expect move operation to be non-throwing.

      Additionally, if a move operation fails, the source object can have been partially altered by the move, making recovery very tricky, or just impossible. Therefore, to ensure robustness, some functions (for instance, std::move_if_noexcept, used by std::vector) will decide to copy your object if its move operations are not decorated with noexcept. This can significantly slow down your program.

      If you can not implement your move operations so that they never throw, you may as well only provide copy operations that will be safer to use.

      Swap operations are very similar to move operations, in that they should be equivalent to moving two objects into each other. So if you are adding a swap function to your type, it should be noexcept too.

      Note that for most classes, you should not write your own move operations, but rely on the "Rule-of-Zero" (S4963).

      This rule raises an issue when a move or swap operation is not noexcept, which can happen in two cases:

      • The operation is user-defined, and is not unconditionally declared as noexcept,
      • The operation is implicitly defined, and one of the base classes or member variables of the class does not have noexcept move operations.

      Noncompliant Code Example

      struct A {
        A (A const &a);
        A (A && a); // Noncompliant
        ~A();
        A &operator=(A const &a);
        A &operator=(A &&a); // Noncompliant
      };
      
      void swap(A& a1, A& a2); // Noncompliant
      

      Compliant Solution

      struct A {
        A (A const &a);
        A (A && a) noexcept;
        ~A();
        A &operator=(A const &a);
        A &operator=(A &&a) noexcept;
      };
      
      void swap(A& a1, A& a2) noexcept;
      

      See

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              alban.auzeill Alban Auzeill
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated: