Main Content

A move operation may throw

Throwing move operations might result in STL containers using the corresponding copy operations

Since R2020b

Description

This defect occurs when a class explicitly declares a move constructor that is missing a noexcept specifier or has a noexcept specifier whose argument evaluates to false. The defect also occurs if an explicitly declared move constructor has the throw(type) exception specification (deprecated in C++11 and removed in C++17).

The checker does not raise a flag if the move constructor is implicitly declared or explicitly declared as =default.

Risk

If a move operation can throw exceptions, some STL containers will use the copy operations instead and not get the performance benefits of a move operation. For instance, the implementation of the std::vector::resize method uses std::move_if_noexcept and performs a move operation for resizing a vector only if the move operation is declared noexcept.

Fix

Add a noexcept specifier to the declaration of the move constructor.

If the move constructor contains expressions that might throw, fix those expressions. To detect violations of the noexcept exception specification, use the checker Noexcept function exits with exception.

Performance improvements might vary based on the compiler, library implementation, and environment that you are using.

Examples

expand all

#include <string>

class Database {
  private:
      std::string* initEntry;
      int size;
  public:
      //Copy constructor
      Database (const Database& other);
      //Move constructor
      Database (Database&& other): initEntry{other.initEntry}, size{other.size} {
      other.initEntry = nullptr;
      other.size = 0;
    }
};

In this example, the Database move constructor does not have a noexcept specification.

Correction – Add noexcept Specifier

Add the noexcept specifier to the move constructor.

#include <string>

class Database {
   private:
       std::string* initEntry;
       int size;
   public:
       //Copy constructor
       Database (const Database& other);
       //Move constructor
       Database (Database&& other) noexcept: initEntry{other.initEntry}, size{other.size} {
       other.initEntry = nullptr;
       other.size = 0;
       }
};

Result Information

Group: Performance
Language: C++
Default: Off
Command-Line Syntax: MOVE_OPERATION_MAY_THROW
Impact: Low

Version History

Introduced in R2020b