发送std::move是正确的方法

Spamming std::move is the way to go?

本文关键字:方法 std move 发送      更新时间:2023-10-16

关于std::move,以下是我可以解释的,根据http://en.cppreference.com/w/cpp/utility/move:-

  • 如果我想转让所有权,我必须调用std::move(或在极少数情况下,std::forward)。
  • std::move的责任呼叫operator=(A&& other)
  • 移动操作的最基本步骤应该在operator=(A&&)中实现。
  • 确保operator=(A&&)会被调用是很棘手的。需要一个特殊的转换器。
  • c++世界中只有两个转换器可以将变量转换为xvalue (&&): std::movestd::forward

在我的代码中添加了许多std::move(std::unique_ptr)之后,我开始担心像转移所有权这样的基本功能,我必须严重依赖标准库(std::)。

我真的必须使用std::move来转移所有权吗?

在代码库的许多地方,垃圾邮件和硬代码调用std::move是一个高标准程序的正确方法吗?

std::move应该被封装吗?

它们实际上是一个问题,但是从不同的角度来问。

编辑

应要求,这是我的试用版& &;错误。它可以编译。
我对代码没有问题,但我担心它的方法/模式。https://ideone.com/y8Pcgf

class T{
    public: int value;
    public: T(int a=1234){
        value = a;
    }
};
int main() {
    std::unique_ptr<T> t1 = std::unique_ptr<T>(new T(1));
    void* databaseNew=operator new [](sizeof(std::unique_ptr<T>));
    std::unique_ptr<T>* t1ptr=static_cast<std::unique_ptr<T>*>(databaseNew);
    new (t1ptr) std::unique_ptr<T>(std::move(t1));
    return 0;
}
经验法则:

如果你在一个推断的x值上下文中,使用std::forward:

template<class T>
void foo(T&& t)       // T is deduced x-value, so we forward it
{
  bar(std::forward<T>(t));
}

否则使用std::move

template<class T>
void foo1(std::vector<T> v)   // although vector<T> is deduced, it's not an x-value
{
    bar(std::move(v));  // so move it
}
template<class T>
void foo2(std::vector<T>&& v)   // although vector<T> is deduced, it's not an x-value. 
                                // In this case an r-value reference
{
    bar(std::move(v));  // so move it
}
template<class T>
void foo3(std::vector<T>& v)   // although vector<T> is deduced, it's not an x-value. 
                               // In this case an l-value reference
{
    bar(std::move(v));  // so move it
}
void foo4(std::vector<int> v)   // complete type
{
    bar(std::move(v));  // so move it
}
void foo5(std::vector<int> const & v)   // const reference
{
    bar(v);  // not much point in moving it. std::move would cast it
             // to std::vector<int> const&&, which although is detectable
             // decays to std::vector<int> const&
}

,虽然可以检测到…怎么啦?

这样写是允许的,但不一定是明智的:

#include <iostream>
struct X
{
  void foo() const &
  {
    // do one thing...
    std::cout << "one thingn";
  }
  void foo() const &&
  {
    // do something else...
    std::cout << "or anothern";
  }
};
int main()
{
  const X x;
  x.foo();
  std::move(x).foo();
}

const r值引用确实存在,只是没有人使用它们,因为没有合理的用例。

您所抱怨的显式move的需要实际上是有意为之。在unique_ptr之前,STL有一个叫auto_ptr的可怕构造。它会隐式地移动所有权,并且是不可用的,除非你真的真的真的知道你在做什么。

为了使事情更可用,在大多数情况下,c++现在要求你通过使用std::move显式地声明你打算转移容器的所有权。

实际上,std::move只不过是一个对右值引用的强制转换。

在某些情况下,这种明确的说明是不必要的。例如,如果您获得所有权的容器已经是右值(例如-临时对象),则不需要使用std::move。例如,以下代码不能编译:

std::unique_ptr<int> a;
a = new int;

但是下面的代码可以,不需要移动:

std::unique_ptr<int> a;
a = std::unique_ptr<int>(new int);

尽管调用了move操作符,但不需要调用std::move的原因是,我们将所有权移开的对象已经是一个临时对象(即-右值),因此不需要强制转换。

另一个例子是,如果你调用一个返回一个unique_ptr的函数。您可能必须在函数内部调用std::move才能将其放入返回值中,但是您不需要在函数的返回值中调用std::move来将其放入外部的unique_ptr中。它已经是右值,因此不需要强制转换。

相关文章: