首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么要搬家?

为什么要搬家?
EN

Stack Overflow用户
提问于 2012-07-30 15:30:16
回答 2查看 577关注 0票数 11

我用美丽的文章阅读了C++11的移动语义,这篇文章是用非常直观的方式写的。本文中的示例类如下所示。

代码语言:javascript
复制
class ArrayWrapper 
{ 
public: 
    // default constructor produces a moderately sized array 
    ArrayWrapper () 
        : _p_vals( new int[ 64 ] ) 
        , _metadata( 64, "ArrayWrapper" ) 
    {} 

    ArrayWrapper (int n) 
        : _p_vals( new int[ n ] ) 
        , _metadata( n, "ArrayWrapper" ) 
    {} 

    // move constructor 
    ArrayWrapper (ArrayWrapper&& other) 
        : _p_vals( other._p_vals  ) 
        , _metadata( other._metadata ) 
    { 
        other._p_vals = NULL; 
    } 

    // copy constructor 
    ArrayWrapper (const ArrayWrapper& other) 
        : _p_vals( new int[ other._metadata.getSize() ] ) 
        , _metadata( other._metadata ) 
    { 
        for ( int i = 0; i < _metadata.getSize(); ++i ) 
        { 
            _p_vals[ i ] = other._p_vals[ i ]; 
        } 
    } 
    ~ArrayWrapper () 
    { 
        delete [] _p_vals; 
    } 
private: 
    int *_p_vals; 
    MetaData _metadata; 
};

显然,在上面的move构造函数实现中,嵌入式元素_metadata不会发生移动。为了方便这一点,诀窍是像这样使用std::move()方法。

代码语言:javascript
复制
ArrayWrapper (ArrayWrapper&& other) 
        : _p_vals( other._p_vals  ) 
        , _metadata( std::move( other._metadata ) ) 
{ 
    other._p_vals = NULL; 
} 

到现在为止还好。

标准上说:

第5条(C++11§5 /6):

[注:表达式如果为x值,则为:

  • 调用函数的结果,无论是隐式的还是显式的,其返回类型是对对象类型的rvalue引用,
  • 转换为对对象类型的rvalue引用,
  • 指定非引用类型的非静态数据成员的类成员访问表达式,其中对象表达式为xvalue,或
  • 一个.*指针到成员表达式,其中第一个操作数是一个xvalue,第二个操作数是指向数据成员的指针。

我的问题是:

现在,移动构造函数中的变量other是一个xvalue (我说得对吗?)然后,根据上面的最后一条规则,other._metadata也应该是xvalue。因此编译器可以隐含地使用_metadata类的move构造函数,所以这里不需要std::move

我遗漏了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-30 15:37:17

你的假设不是真的。构造函数的参数是xvalue,它允许绑定rvalue-引用,但是一旦rvalue-引用被绑定,在构造函数中,它不再是xvalue,而是lvalue。从概念上讲,调用地的对象正在过期,但在构造函数内部,直到它完成,它不再过期,因为它可以稍后在构造函数块中使用。

代码语言:javascript
复制
ArrayWrapper f();
ArrayWrapper r = f();   // [1]

在1中,表达式f()引用了一个临时表达式,它在调用构造函数之后将过期,因此它可以被一个rvalue引用绑定。

代码语言:javascript
复制
ArrayWrapper (ArrayWrapper&& other) 
    : _p_vals( other._p_vals  ) 
    , _metadata( other._metadata )        // [2] 
{ 
    other._p_vals = NULL; 
    std::cout << other._metadata << "\n"; // [3]
} 

在构造函数中,other不过期,它将对构造函数的每条指令都是活动的。如果编译器允许在2中移动,那么进一步使用3中的变量将是无效的。您必须显式地告诉编译器,您希望该值现在到期。

票数 15
EN

Stack Overflow用户

发布于 2012-07-30 15:32:25

other是一个L值,因为它是一个变量。命名引用是lvalue,不管它们是什么类型的引用。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11724592

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档