c++ - 我是否经常使用 std::move() ?

标签 c++ c++17 move move-semantics

我终于觉得我理​​解了现代 C++ 中的 move 语义,并且它在我编写代码的方式上发生了巨大的变化。现在,我正在开发一个使用依赖注入(inject)的应用程序,我正在结合我对 move 语义的新知识,但我最终使用了太多的 std::move() 以至于我担心我使用不当。

以前,如果我想在我的对象中注入(inject)一个我需要一个拷贝的依赖项,我会这样编写我的构造函数:

class NeedsCopyOfFoo
{
public:
  NeedsCopyOfFoo(const Foo& foo)
    : m_myFoo{foo} {}
private:
  Foo m_myFoo;
};

现在,我的类看起来像这样:

class NeedsCopyOfFoo
{
public:
  NeedsCopyOfFoo(Foo foo)
    : m_myFoo{std::move(foo)} {}
private:
  Foo m_myFoo;
};

在我的设计中有一些类需要多达三四个类类型的依赖关系,我最终将它们全部 move 了。显然,如果我的构造函数的调用者无法使用右值调用构造函数,而且在构造 NeedsCopyOfFoo 对象后也不打算使用依赖项,我还需要使用 std::move() 在那里,以避免完全不必要的复制。

这就是现代 C++ 的样子吗? Bob 大叔是否提到了“过于频繁地使用 std::move()”的代码味道?我是不是 react 过度了,因为我还不习惯用这种新风格写作?

最佳答案

TL;DR:如果您不关心完美的性能,那么

Class(const Foo& foo, const Bar& bar, ...) : m_myFoo{foo}, m_myBar{bar}, ...{...} {}

是你的构造函数。它需要右值/左值,并且会花费你一份拷贝。它是您所能得到的最好的东西,让生活变得轻松,拥有轻松的生活还有很多话要说。


对于一个变量,我会设置一个重载

NeedsCopyOfFoo(Foo&& foo) : m_myFoo{std::move(foo)} {}
NeedsCopyOfFoo(const Foo& foo) : m_myFoo{foo} {}

这最多花费一次复制或一次 move 操作,具体取决于传递给构造函数的对象类型。这是你能得到的最完美的。

不幸的是,这并不能很好地扩展。当您开始添加更多您想要以相同方式处理的参数时,过载集会呈二次方增长。这一点都不好玩,因为 4 参数构造函数需要 16 次重载才能完美。为了解决这个问题,我们可以使用转发构造函数并将其限制为 SFINAE所以它只需要你想要的类型。那会给你一个像

这样的构造函数
template<typename T, 
         typename U, 
         std::enable_if_t<std::is_convertible_v<T, Foo> &&
                          std::is_convertible_v<U, Bar>, bool> = true>
Class(T&& foo, U&& bar) : 
    m_myFoo{std::forward<T>(foo)}, 
    m_myBar{std::forward<U>(bar)} {}

这为您提供了最佳性能,但如您所见,它非常冗长,需要您了解更多有关 C++ 的知识才能使用。

关于c++ - 我是否经常使用 std::move() ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57923963/

相关文章:

c++ - [conv]/6中语句 "The expression e is used as a glvalue if and only if the initialization uses it as a glvalue"的确切含义是什么

c++ - 标准库 `emplace` 函数是否使用 `std::in_place` 标签

Android Eclipse - move 项目导致所有 R 引用错误

Python启动程序: Moving files

c++ - 尝试在按下时消除此按钮的抖动

c++ - VCL 应用程序何时获取其 Application->MainForm->Handle?

c++ - 如何在 C++ 中创建类型列表的 n 路笛卡尔积?

c++ - 有没有办法绕过不同编译器上的 printf 错误?

c++ - NULL 和 C++ 中的 False 一样吗

php - 将数据从一个表 move 到另一个表时出错