2013-05-29 76 views
3

这个“移动”语义的目的究竟是什么?我明白如果你不通过引用传入一个副本是由非原始类型组成的,但“move”如何改变任何东西?我们为什么要“移动”数据?为什么不能将它保存在同一地址而不能复制?如果它被发送到另一个地址,是不是只是一个“复制和删除”?C++移动语义 - 它究竟要达到什么目的?

总之,我并没有真正明白什么是语义学正在实现。

+2

对我来说很好阅读http://thbecker.net/articles/rvalue_references/section_01.html –

回答

1

为什么不能只是在同一个地址保存,并不会复制

这其实就是移动语义一般不。它经常以完全相同的状态保存资源(通常是内存,但可以是文件句柄等),但它会更新对象中的引用。

想象两个向量,srcdestsrc矢量包含在堆上分配的大块数据,并且dest为空。当src被移动到dest发生的所有情况是dest被更新为指向堆上的内存块,而src被更新为指向任何dest指向的内容,在这种情况下什么也没有。

为什么这很有用?因为这意味着可以写入vector,只有一个向量会指向它分配的内存块。这意味着析构函数可以确保它清理已分配的内存。

这可以扩展用于管理其他资源的对象,例如文件句柄。现在可以编写可拥有文件句柄的对象。这些对象可以移动,但不可复制。由于STL容器支持可移动对象,因此它们可以放在容器中比在C++ 03中容易得多。它们的文件句柄或其他资源只能保证引用它,并且析构函数可以适当地关闭它。

2

移动语义结合了按值传递和按引用传递的优点。您可以静态分配类,因此您不必为其生命周期负责,并且可以将它们作为参数传递并轻松地从函数返回。另一方面,在这种情况下,当通常对象被复制时,它们被移动(只复制它们的内部)。此操作可能比复制执行时间少很多(因为您知道,rhs对象将不再使用)。

MyObj * f() 
{ 
    // Ok, but caller has to take care of 
    // freeing the result 
    return new MyObj(); 
} 

MyObj f() 
{ 
    // Assuming, that MyObj does not have move-ctor 
    // This may be time-costly 
    MyObj result; 
    return result; 
} 

MyObj f() 
{ 
    // This is both fast and safe 
    MyObj result; 
    return std::move(result); 

    // Note, if MyObj implements a move-ctor, 
    // usually you don't have to call std::move. 
} 
0

我与向量代数一个简单的例子回答:

class Vector{ 
    size_t dim_; 
    double *data_; 
public: 
    Vector(const Vector &arg) 
    : dim_(arg.dim_) 
    , data_(new double[dim_]) 
    { 
    std::copy_n(arg.data_, dim_, data_); 
    } 

    Vector(Vector &&arg) 
    : dim_(arg.dim_) 
    , data_(arg.data_) 
    { 
    arg.data_ = nullptr; 
    } 

    ~Vector() 
    { 
    delete[] data_; 
    } 

    Vector& operator+= (const Vector &arg) 
    { 
    if (arg.dim_ != dim_) throw error; 
    for (size_t idx = 0; idx < dim_; ++idx) data_[idx] += arg.data_[idx]; 
    return *this; 
    } 
}; 

Vector operator+ (Vector a, const Vector &b) 
{ 
    a += b; 
    return a; 
} 

extern Vector v1, v2; 

int main() 
{ 
    Vector v(v1 + v2); 
} 

添加按值返回一个新的载体。因为它是一个r值,所以转换为v,这意味着将不会发生潜在巨大数组data_的额外副本。