2

更新在底部。

我想让 void tree::operator = ( tree t ) 使用右值。(在这种情况下,一般来说,由于效率,我想以不同的方式处理它们)

我已经对其进行了编码,使用 std::move 来确保它将使用右值,但编译器说它不知道选择哪个运算符。他不应该使用右值选择那个吗?

代码:

void tree::operator = ( tree&& t )
{
  std::swap(this->pntr, t.pntr);
}

void tree::operator = ( tree t )
{
  *this = std::move(t);
}

编译器错误:

tree.cpp:23:9: error: use of overloaded operator '=' is ambiguous (with operand types 'tree' and 'typename remove_reference<tree &>::type' (aka 'tree'))
  *this = std::move(t);
  ~~~~~ ^ ~~~~~~~~~~~~
tree.cpp:16:12: note: candidate function
void tree::operator = ( tree&& t )
           ^
tree.cpp:21:12: note: candidate function
void tree::operator = ( tree t )
           ^
1 error generated.

我正在使用 clang-503.0.38。(但使用 gcc 4.8 是同样的错误)

更新

好的,现在我有:

tree& tree::operator = ( tree&& t )
{
  std::swap(this->pntr, t.pntr);
}

tree& tree::operator = ( const tree & t )
{
  *this = tree(t); // tree:tree( const tree& t )
}

它正在工作。明天我将发布我从中学到的东西作为答案。

4

2 回答 2

3

您可以只编写一个版本 tree::operator=(tree t) ,它使用复制和交换习惯用法实现,同时提供了复制构造函数和移动构造函数。

因此,班级客户可以选择复制作业,例如:

tree1 = tree2;

, 同时也可以选择移动赋值例如:

tree1 = std::move(tree2);
于 2014-03-27T11:12:33.640 回答
2

您的代码有几个问题:

  • 赋值运算符应该返回对对象本身的引用。也就是说,应该返回tree&,而不是void

  • 两者tree::operator=( tree other )tree::ooperator( tree&& other )都可以采用右值,因此重载是不明确的。如果您只需要/想要右值分配,则基于复制和交换的右值分配是正确的,但是如果您同时需要右值和左值,则应仅通过值分配提供并在其上使用复制和交换习语

    tree& tree::operator=( tree other )
    {
        using std::swap; //Enable ADL (Not strictly neccesary, but good practice)
    
        swap( *this , other );
    
        return *this;
    }
    

    请注意,您应该编写一个自定义swap()函数来打破std::swap()默认实现的潜在无限递归。阅读此线程以了解有关复制和交换习语的更多注意事项。

于 2014-03-27T11:22:55.063 回答