【问题标题】:Explicitly select copy assignment显式选择复制分配
【发布时间】:2018-06-25 05:58:35
【问题描述】:

在 C++11 中,如果复制和移动赋值都可用,编译器会在参数是左值时自动选择复制赋值,如果是右值则自动选择移动赋值。使用std::move 可以显式选择左值的移动分配。但是怎么可能显式地选择右值的复制赋值呢?

代码示例:

#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;
}

【问题讨论】:

  • 您可以将static_cast 转为const int&amp; : test = static_cast&lt;const int&amp;&gt;(3);
  • @rahnema1 评论不是用来回答的,你知道...
  • @NickyC :有时只想写一句话,而一句话很少是一个好的答案。 ;-]
  • 如果您同时拥有这两个运算符,则编写该功能以正确处理参数。出于这个原因,“手动”选择不同的运算符作为“自然正确”的运算符看起来不是很有用。与 std::move 一样,它会导致对象“无效状态”。如果这是预期的,很好!但是如果将右值作为左值处理呢?
  • 我很好奇这样做的动机

标签: c++ c++11


【解决方案1】:

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

template <class T>
constexpr T& copy(T&& t) noexcept
{
    return t;
}

你可以这样测试:

test = copy(a);
test = copy(3);
test = copy(std::move(a));

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


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

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

【讨论】:

  • @NikosC。 - std::move 接受转发引用。价值观不会“立即消失”。您可以将右值引用绑定到右值因为它有一些生命周期保证。
  • @codekaizer 这样的std::copy 根本不存在。一个不存在的东西显然是行不通的。 (虽然有一个名为std::copy的函数,但它不是我们在这里想象的那个。)
  • 由于copystd中已经有了不同的含义,而且由于这实际上是std::move的反转,所以我通常在我的实用程序中将此函数称为stay
  • @Angew std::move 也有两种含义 ;) (转换为 xvalue 并将范围移动到另一个)
  • 好吧,我不会称它为copy,因为它看起来应该返回一个副本!另外,你忘了noexcept
【解决方案2】:

您可以将static_cast 转为const int&amp;

test = static_cast<const int&>(3);

【讨论】:

  • 添加const 有一个微妙的缺点,对于std::auto_ptr 之类的东西会失败。 (是的,这是一个完全邪恶的例子,但偶尔有用的概念)
  • @o11c 但是由于无论如何您都需要根据具体情况编写此代码,包括手动确定要替换 int 的内容,您可以选择在案例中省略 const - 如果您愿意,可以根据具体情况。
  • @o11c 有趣,我没有意识到这一点!
  • @o11c 我认为std::auto_ptr 已被弃用,甚至可能在 c++17 中被删除?
猜你喜欢
  • 2020-11-22
  • 1970-01-01
  • 2018-03-04
  • 2019-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
相关资源
最近更新 更多