C++11 C++;11对象为成员的类的移动赋值运算符-初学者级别

C++11 C++;11对象为成员的类的移动赋值运算符-初学者级别,c++11,move,C++11,Move,我有一个关于c++11中移动辅助的初学者问题。假设我有一个a级,配备了移动辅助操作符: class A { public: A(); ~A(); A& operator=(A&&); ... } 我还有一个包含a类对象的B类,并提供了一个移动赋值操作符 class B { public: B(); ~B(); B& operator=(B&&); ... private: A Test

我有一个关于c++11中移动辅助的初学者问题。假设我有一个a级,配备了移动辅助操作符:

class A
{
 public:
   A();
  ~A();
  A& operator=(A&&);
  ...
}
我还有一个包含a类对象的B类,并提供了一个移动赋值操作符

class B
{
 public:
     B();
    ~B();
   B& operator=(B&&);
    ...
 private:
   A Test;
}
我的想法是,B移动分配运算符将调用其成员的移动分配运算符,因此我尝试了以下方法:

B& B::operator=(B&& Other)
{
  ...
  Test = Other.Test;
  ...
  return *this;
}
B& B::operator=(B&& Other)
{
  ...
  Test = std::move(Other.Test);
  ...
  return *this;
}
但这不起作用,因为类A的移动赋值未被调用

相反,我能够通过使用以下方法使程序工作:

B& B::operator=(B&& Other)
{
  ...
  Test = Other.Test;
  ...
  return *this;
}
B& B::operator=(B&& Other)
{
  ...
  Test = std::move(Other.Test);
  ...
  return *this;
}

我不明白为什么第一种方法不起作用。我在想,既然构造函数将调用其成员构造函数,那么move赋值操作符也应该这样做。我是错了还是我的代码出错了?谁能解释一下,谢谢

Other.Test
不是右值表达式,因为它有一个名称。OTOH
std::move(Other.Test)
具有类型
A
和值类别xvalue(即右值)。因此,它可以绑定到move构造函数


(编辑:无耻地复制了@dyp的评论。谢谢,@dyp和@KerrekSB。)

其他。Test
不是右值表达式,因为它有一个名称。OTOH
std::move(Other.Test)
具有类型
A
和值类别xvalue(即右值)。因此,它可以绑定到move构造函数


(编辑:无耻地复制了@dyp的评论。谢谢,@dyp和@KerrekSB。)

其他。Test
不是右值表达式,因为它有一个名称。OTOH
std::move(Other.Test)
具有类型
A
和值类别xvalue(即右值)。因此,它可以绑定到move构造函数


(编辑:无耻地复制了@dyp的评论。谢谢,@dyp和@KerrekSB。)

其他。Test
不是右值表达式,因为它有一个名称。OTOH
std::move(Other.Test)
具有类型
A
和值类别xvalue(即右值)。因此,它可以绑定到move构造函数


(编辑:厚颜无耻地复制了@dyp的评论。谢谢,@dyp和@KerrekSB。)

@Pradhan是正确的-您需要使用
std::move
在move assignment操作符的实现中移动成员。但是,如果这是实现移动构造函数所需的全部内容,则可以声明运算符以使用默认实现:

#include <memory>

class A {
public:
    A() : p{} { }
    ~A() { }

    A &operator=(A &&) = default;

    // Instead of:
    //    A &operator=(A &&other) {
    //        p = std::move(other.p);
    //        return *this;
    //    }

private:
    std::unique_ptr<int> p;
};

int main() {
    A a;
    A b;
    b = std::move(a);

    return 0;
}
#包括
甲级{
公众:
A():p{}{}
~A(){}
A&运算符=(A&&)=默认值;
//而不是:
//A&运算符=(A&&其他){
//p=标准::移动(其他.p);
//归还*这个;
//    }
私人:
std::唯一的ptr p;
};
int main(){
A A;
A b;
b=标准::移动(a);
返回0;
}

@Pradhan是正确的-您需要使用
std::move
在move赋值操作符的实现中移动成员。但是,如果这是实现移动构造函数所需的全部内容,则可以声明运算符以使用默认实现:

#include <memory>

class A {
public:
    A() : p{} { }
    ~A() { }

    A &operator=(A &&) = default;

    // Instead of:
    //    A &operator=(A &&other) {
    //        p = std::move(other.p);
    //        return *this;
    //    }

private:
    std::unique_ptr<int> p;
};

int main() {
    A a;
    A b;
    b = std::move(a);

    return 0;
}
#包括
甲级{
公众:
A():p{}{}
~A(){}
A&运算符=(A&&)=默认值;
//而不是:
//A&运算符=(A&&其他){
//p=标准::移动(其他.p);
//归还*这个;
//    }
私人:
std::唯一的ptr p;
};
int main(){
A A;
A b;
b=标准::移动(a);
返回0;
}

@Pradhan是正确的-您需要使用
std::move
在move赋值操作符的实现中移动成员。但是,如果这是实现移动构造函数所需的全部内容,则可以声明运算符以使用默认实现:

#include <memory>

class A {
public:
    A() : p{} { }
    ~A() { }

    A &operator=(A &&) = default;

    // Instead of:
    //    A &operator=(A &&other) {
    //        p = std::move(other.p);
    //        return *this;
    //    }

private:
    std::unique_ptr<int> p;
};

int main() {
    A a;
    A b;
    b = std::move(a);

    return 0;
}
#包括
甲级{
公众:
A():p{}{}
~A(){}
A&运算符=(A&&)=默认值;
//而不是:
//A&运算符=(A&&其他){
//p=标准::移动(其他.p);
//归还*这个;
//    }
私人:
std::唯一的ptr p;
};
int main(){
A A;
A b;
b=标准::移动(a);
返回0;
}

@Pradhan是正确的-您需要使用
std::move
在move赋值操作符的实现中移动成员。但是,如果这是实现移动构造函数所需的全部内容,则可以声明运算符以使用默认实现:

#include <memory>

class A {
public:
    A() : p{} { }
    ~A() { }

    A &operator=(A &&) = default;

    // Instead of:
    //    A &operator=(A &&other) {
    //        p = std::move(other.p);
    //        return *this;
    //    }

private:
    std::unique_ptr<int> p;
};

int main() {
    A a;
    A b;
    b = std::move(a);

    return 0;
}
#包括
甲级{
公众:
A():p{}{}
~A(){}
A&运算符=(A&&)=默认值;
//而不是:
//A&运算符=(A&&其他){
//p=标准::移动(其他.p);
//归还*这个;
//    }
私人:
std::唯一的ptr p;
};
int main(){
A A;
A b;
b=标准::移动(a);
返回0;
}


@dyp我不明白。当我的意思是说
std::move(Other.Test)
返回一个右值引用时,说它有类型右值引用是不正确的吗?@Pradhan:正确的说法是“
std::move(Other.Test)
是一个右值”。它的类型是
A
std::move
返回一个右值引用,但任何表达式类型的任何引用限定符都会立即删除以形成值类别。例如,表达式
std::move(Other.Test)
具有类型
A
和值类别xvalue(即,一个右值)。@dyp:为了恰当地迂腐,您不能“返回引用”(因为函数调用确实是表达式)。相反,您可以说“std::move的返回类型是一个右值引用”,或者“
std::move
返回一个xvalue”。@KerrekSB您可能是对的,但我想知道函数返回类型是否真的是技术语言。它在库部件中多次出现;但不是在核心语言部分(“返回一个ref”)--My
std::move
标识一组函数模板,而不是一个表达式。@dyp我不懂。当我的意思是说
std::move(Other.Test)
返回一个右值引用时,说它有类型右值引用是不正确的吗?@Pradhan