2013-05-29 2 views
3

В чем же цель этой семантики «двигаться»? Я понимаю, что если вы не проходите по ссылке, копия сделана из не-примитивных типов, но как «переместить» что-то изменить? Почему мы хотим «переместить» данные? Почему это не может быть сохранено по одному и тому же адресу и не скопировано? Если он отправляется на другой адрес, это не просто «копировать и удалять»?C++ move semantics - что именно он должен достичь?

Короче говоря, я действительно не понимаю, к чему именно стремится семантика.

+2

очень хорошее чтение для меня http://thbecker.net/articles/rvalue_references/section_01.html –

ответ

1

Почему косяк это просто быть по тому же адресу и не копируются

Это на самом деле то, что движение семантики обычно делает. Он часто хранит ресурс (часто память, но может быть файловым дескриптором и т. Д.) В одном и том же состоянии, но он обновляет ссылки в объектах.

Представьте себе два вектора, src и dest. Вектор src содержит большой блок данных, который выделяется в куче, а 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_ не произойдет.

Смежные вопросы