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

"std::move" should only be used where moving can happen

    XMLWordPrintable

    Details

    • Default Severity:
      Major
    • Impact:
      Low
    • Likelihood:
      High
    • Default Quality Profiles:
      Sonar way
    • Covered Languages:
      C++
    • Remediation Function:
      Constant/Issue
    • Constant Cost:
      10min
    • CppCoreGuidelines:
      ES.56

      Description

      Calling std::move on objects that cannot be moved is suspicious and might hide nasty performance bug.

      This can happen when calling std::move with const argument or with non-movable types.

      This can also happen when passing the result of std::move as a const reference argument.  In this case, no object will be moved since the result is in a context where calling the move constructor is not possible. It makes sense to call std::move on a function argument when:

      • The result of std::move is passed as an r-value reference.
      • The result of std::move is passed by copy.

      Noncompliant Code Example

      struct NonMovable{
        NonMovable() = default;
        NonMovable(NonMovable&) = default;
      };
      
      void f(NonMovable s);
      void f(std::string s);
      void g(const std::string &s);
      
      void test() {
        std::string s="****";
        f(std::move(s));
        g(std::move(s)); // Noncompliant: s is cast back to const l-value reference. s will not be moved.
      
        const std::string constS="***";
        f(std::move(constS)); // Noncompliant: constS will not be moved.
      
        NonMovable t;
        f(std::move(t)); // Noncompliant: std::move is useless on non-movable objects like t. Copy constructor is called.
      }
      

      Compliant Solution

      struct Movable{
        Movable() = default;
        Movable(Movable&) = default;
        Movable(Movable&&) = default;
      };
      
      void f(Movable);
      void f(std::string s);
      void g(const std::string &s);
      
      void test() {
        std::string s="****";
        f(std::move(s)); // Compliant:  move constructor is called.
        g(s); // Compliant: no misleading std::move is used.
      
        Movables t;
        f(std::move(t)); // Compliant: move constructor is called.
      }
      

      See

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              geoffray.adde Geoffray Adde
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated: