【问题标题】:How to make rvalue method correctly call move constructor如何使右值方法正确调用移动构造函数
【发布时间】:2017-04-02 10:58:54
【问题描述】:

我有这样的复制和移动构造函数的基类:

class Test {
 public:
    Test( int i ) {
        iptr = new int( i );
    }
    Test( const Test & other ) {
        printf("copy constructor\n");
        iptr = new int( *other.iptr );
    }
    Test( Test && other ) {
        printf("move constructor\n");
        iptr = other.iptr;
        other.iptr = NULL;
    }
    virtual ~Test() {
        delete iptr;
    }
    virtual Test * copy() {
        return new Test( *this );
    }
    virtual Test * move() && {
        return new Test( *this );
    }
 protected:
    int * iptr;
};

我添加了一个复制和移动方法来允许多态复制和移动对象从一个指针,它可以潜在地指向某个子类的一个实例。

但是当我写以下内容时

Test t1( 5 );
Test * t2 = t1.copy();
Test * t3 = Test( 6 ).move();

第一种情况正确调用了复制构造函数,但第二种情况也错误地调用了复制构造函数。

为什么构造函数重载不能正常工作,如何让它调用移动构造函数?

【问题讨论】:

  • 为什么不将复制方法“标记”为 const 到它的实例?
  • @LaurentG:哦,我忘了。但在这两种情况下它仍然调用复制构造函数。
  • return new Test(std::move(*this));

标签: c++ constructor move-semantics


【解决方案1】:

与任何右值引用参数都是函数内的左值一样,调用右值引用限定成员函数的对象是该成员函数内的左值。

void foo(Test&& x) 
{ 
    /* here x is an lvalue ! */ 
    Test y(std::move(x)); // need explicit cast to actually move
}

因此你需要:

virtual Test * move() && {
    return new Test( std::move(*this) );
}

(别忘了#include <utility>。)

*this 是左值的原因是因为指针间接寻址总是产生一个左值,其中this 总是在T 类型的成员函数中是T*(或T cv *)。虽然成员函数 cv 限定会影响 this 指针,但函数的 ref 限定不会。 (没有“指向右值的指针”或“指向左值的指针”,只有“指向 const 的指针”或“指向 volatile 的指针”等)


【讨论】:

  • 为什么一个右值在函数内部又变成左值了?
  • @Youda008:我链接了几个相关的问题。
猜你喜欢
  • 1970-01-01
  • 2016-03-28
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
  • 2017-11-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多