明确选择复制分配

Jul*_*ich 30 c++ c++11

在C++ 11中,如果复制和移动赋值都可用,则编译器会在参数为左值时自动选择复制赋值,如果是左值则移动赋值.使用std::move它可以明确地选择左值的移动分配.但是如何明确选择rvalue的复制赋值呢?

代码示例:

#include <iostream>

class testClass
{
public:
    testClass &operator=(const int &other) {
        std::cout << "Copy assignment chosen." << std::endl;
        return *this;
    }

    testClass &operator=(int &&other) {
        std::cout << "Move assignment chosen." << std::endl;
        return *this;
    }   
};  

int main(int argc, char *argv[])
{
    int a = 4;
    testClass test;

    test = a; // Selects copy assignment
    test = 3; // Selects move assignment

    test = std::move(a); // Selects move assignment
//  test = std::copy(3); // <--- This does not work

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

小智 19

一种可能的方法是编写自己copy的对象以将对象绑定到左值引用:

template <class T>
constexpr T& copy(T&& t) noexcept
{
    return t;
}
Run Code Online (Sandbox Code Playgroud)

你可以这样测试它:

test = copy(a);
test = copy(3);
test = copy(std::move(a));
Run Code Online (Sandbox Code Playgroud)

您可以将此函数放在自己的命名空间中以保持清洁.您也可以为它选择一个更好的名称.


为了解决生命问题的恐惧,这里有一些注意事项:

  • copy函数接受引用并立即返回相同的引用.这意味着调用者负责控制生命周期.
  • 临时对象的生命周期一直持续到语句结束.这使得对象持续足够长的时间以传递到左侧=.

  • @NikosC. - `std :: move`采用转发引用.价值观不会"立即消失".您可以将r值引用绑定到rvalue*,因为*它具有一些生命周期保证. (3认同)
  • @codekaizer这样的`std :: copy`根本不存在.一个不存在的东西显然不起作用.(虽然有一个名为`std :: copy`的函数,但它不是我们想象的那个.) (3认同)
  • 由于`copy`在`std`中已经有了不同的含义,因为这实际上是`std :: move`的反转,所以我通常在我的实用程序中调用这个函数`stay`. (3认同)
  • 好吧,我不会称它为'copy`,因为它看起来应该返回一个副本!而且,你忘记了'noexcept`. (3认同)
  • @Angew`std :: move`也有两个含义;)(强制转换为xvalue并将范围移动到另一个) (2认同)

rah*_*ma1 8

你可以static_castconst int&:

test = static_cast<const int&>(3);
Run Code Online (Sandbox Code Playgroud)

  • 这有一个微妙的缺点,即添加`const`,这对于像`std :: auto_ptr`这样的东西来说是失败的.(是的,这是一个完全邪恶的例子,但偶尔有用的概念) (5认同)
  • @ o11c但是既然你需要逐个编写这个代码,包括手动找出替换`int`的内容,你可以根据具体情况选择省略`const`如果你愿意的话. (3认同)
  • @ArthurTacca`static_cast <int&>(3)`编译失败,`const_cast <int&>(static_cast <const int&>(3))`如果你真的做过任何突变,那就是UB. (3认同)