gpt4 book ai didi

c++ - 值传递和 std::move 优于传递引用的优点

转载 作者:IT老高 更新时间:2023-10-28 12:09:25 27 4
gpt4 key购买 nike

我目前正在学习 C++,并尽量避免养成坏习惯。据我了解,clang-tidy 包含许多“最佳实践”,我尽量坚持使用它们(尽管我还不一定了解 为什么 它们被认为是好的),但是我不确定我是否理解这里的建议。

我使用了教程中的这个类:

class Creature
{
private:
std::string m_name;

public:
Creature(const std::string &name)
: m_name{name}
{
}
};

这导致 clang-tidy 建议我应该按值而不是引用传递并使用 std::move。如果我这样做了,我会收到将 name 设为引用的建议(以确保它不会每次都被复制)以及 std::move 不会出现的警告任何效果,因为 nameconst 所以我应该删除它。

我没有收到警告的唯一方法是完全删除 const:

Creature(std::string name)
: m_name{std::move(name)}
{
}

这似乎是合乎逻辑的,因为 const 的唯一好处是防止弄乱原始字符串(这不会发生,因为我按值传递)。但我继续阅读 CPlusPlus.com :

Although note that -in the standard library- moving implies that the moved-from object is left in a valid but unspecified state. Which means that, after such an operation, the value of the moved-from object should only be destroyed or assigned a new value; accessing it otherwise yields an unspecified value.

现在想象一下这段代码:

std::string nameString("Alex");
Creature c(nameString);

因为 nameString 是按值传递的,所以 std::move 只会使构造函数内部的 name 无效,而不会触及原始字符串。但是这样做有什么好处呢?无论如何,内容似乎只被复制一次 - 如果我在调用 m_name{name} 时通过引用传递,如果我在传递它时通过值传递(然后它被移动)。我知道这比按值传递而不使用 std::move 更好(因为它被复制了两次)。

那么两个问题:

  1. 我是否正确理解了这里发生的事情?
  2. 使用 std::move 比通过引用传递和调用 m_name{name} 有什么好处吗?

最佳答案

/* (0) */ 
Creature(const std::string &name) : m_name{name} { }
  • 传递的左值绑定(bind)到name,然后复制m_name

  • 传递的rvalue 绑定(bind)到name,然后复制m_name


/* (1) */ 
Creature(std::string name) : m_name{std::move(name)} { }
  • 传递的左值复制name,然后移动m_name .

  • 传递的 rvalue移动name,然后被 移动m_name .


/* (2) */ 
Creature(const std::string &name) : m_name{name} { }
Creature(std::string &&rname) : m_name{std::move(rname)} { }
  • 传递的左值绑定(bind)到name,然后复制m_name

  • 传递的rvalue 绑定(bind)到rname,然后移动m_name


由于移动操作通常比复制操作更快,因此如果您通过大量临时操作,(1) 优于 (0)(2) 在复制/移动方面是最佳的,但需要重复代码。

完美转发可以避免代码重复:

/* (3) */
template <typename T,
std::enable_if_t<
std::is_convertible_v<std::remove_cvref_t<T>, std::string>,
int> = 0
>
Creature(T&& name) : m_name{std::forward<T>(name)} { }

您可能希望限制 T 以限制可以实例化此构造函数的类型域(如上所示)。 C++20 旨在通过 Concepts 简化这一点.


在 C++17 中,prvaluesguaranteed copy elision 影响,在适用的情况下,这将减少向函数传递参数时的复制/移动次数。

关于c++ - 值传递和 std::move 优于传递引用的优点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51705967/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com