当参数类没有移动构造函数时,IDE 建议“按值传递并使用 std move”

60q*_*60q 3 c++ variables move-semantics

struct Person
{
    int mId; 
    std::string mName; 

    Person(int id, std::string name) : mId(id), mName(std::move(name))
    {
    }
};

struct Node
{
    Person mData;  
    Node* mLeft;
    Node* mRight;

    Node(Person data) : mData(std::move(data)), mLeft(nullptr), mRight(nullptr)
    {}
};
Run Code Online (Sandbox Code Playgroud)

在为 Person 类编写构造函数时,我最初将“name”参数定义为 const 引用,但建议将其更改为简单值并使用 std move

我理解这是因为右值字符串可用于初始化“Person”,在这种情况下,该字符串将被移动到变量“name”中而不是被复制。然后它将通过 std::move 进一步移动到成员变量“mName”中。我还认为这仅适用于 std::string 因为它定义了一个移动构造函数。

不明白的是为什么建议我在“Node”类构造函数中再次使用 std::move ,因为我没有为 Person 定义移动构造函数。此外,我注意到从 Person 类中删除字符串成员变量 mName 会停止此 IDE 推荐。

我的猜测是,这是因为 Person 类的默认移动构造函数。

如果有帮助的话,我的 IDE 是 VS2022,推荐来自扩展 Resharper'

use*_*522 5

您的Person类遵循“零规则”,这意味着它不会显式声明任何复制/移动操作或析构函数。

这通常是正确的做法,因为编译器将隐式声明所有这些操作,并使用您通常期望从这些操作中获得的语​​义来定义它们(如果可能的话)。

在您的情况下, 的所有成员都Person可以移动构造,因此Person将定义 的隐式移动构造函数来逐一移动构造成员。

这是添加时使用std::movemData(std::move(data))。如果没有它,它data就是左值,而是使用隐式复制构造函数来复制构造每个成员。

复制构造 astd::string通常比移动构造 a 成本更高,这可能就是该工具对这种情况发出警告的原因,但如果std::string不存在则不会发出警告。移动构造和复制构造int成员是完全相同的操作。

如果您不想每次都检查类有哪些成员,则可以std::move在这些情况下始终使用。例如,更改mId(id)mId(std::move(id))是毫无意义的,因为id是标量类型,但它也不会让任何事情变得更糟。