Подтвердить что ты не робот

Copy vs std:: move for ints

  • Какая разница между копией по умолчанию и std:: move в этом примере?
  • После move у объекта есть зависимость между новым и старым?
int main () {

    int a = 100;
    std::cout<<&a<<std::endl;

    auto a_copy = a;                 // deduced as int
    std::cout<<&a_copy<<std::endl;

    auto a_move = std::move(a);      // deduced as int
    std::cout<<&a_move<<std::endl;

};

выход:

0x7fffffffe094
0x7fffffffe098
0x7fffffffe09c
4b9b3361

Ответ 1

В этом примере нет разницы. В итоге мы получим 3 int со значением 100. Однако определенно может быть разница с разными типами. Например, рассмотрим что-то вроде vector<int>:

std::vector<int> a = {1, 2, 3, 4, 5}; // a has size 5
auto a_copy = a;                      // copy a. now we have two vectors of size 5
auto a_move = std::move(a);           // *move* a into a_move

Последняя переменная a_move принимает права на внутренние указатели a. Итак, в итоге мы имеем a_move - вектор размера 5, но a теперь пуст. move намного эффективнее, чем a copy (представьте, если бы это был вектор из 1000 строк вместо этого; a_copy включал бы выделение 1000-строкового буфера и копирование 1000 строк, но a_move просто назначает пару указателей).

Для некоторых других типов может быть недействительным:

std::unique_ptr<int> a{new int 42};
auto a_copy = a;            // error
auto a_move = std::move(a); // OK, now a_move owns 42, but a points to nothing

Для многих типов нет никакой разницы:

std::array<int, 100> a;
auto a_copy = a;            // copy 100 ints
auto a_move = std::move(a); // also copy 100 ints, no special move ctor

В более общем плане:

T a;
auto a_copy = a;            // calls T(const T& ), the copy constructor
auto a_move = std::move(a); // calls T(T&& ), the move constructor

Ответ 2

Использование std::move просто изменяет lvalue на значение x, поэтому оно может использоваться с конструкторами перемещения и переместить операторы присваивания. Они не существуют для встроенных типов, поэтому использование перемещения не влияет на этот пример.

Ответ 3

Какая разница между копией по умолчанию и std:: move в этом примере?

Нет никакой разницы. Копирование чего-либо удовлетворяет требованиям перемещения, а в случае встроенных типов перемещение выполняется как копия.

После перемещения объекта существует какая-либо зависимость между новым и старым

Нет, никаких зависимостей нет. Обе переменные независимы.

Ответ 4

Чтобы развернуть на другом плакате ответ, парадигма move-is-a-copy применяется ко всем структурам данных, состоящим из типов POD (или состоящих из других типов, состоящих из типов POD), а также в этом примере:

struct Foo
{
    int values[100];
    bool flagA;
    bool flagB;
};

struct Bar
{
    Foo foo1;
    Foo foo2;
};

int main()
{
    Foo f;
    Foo fCopy = std::move(f);
    Bar b;
    Bar bCopy = std::move(b);
    return 0;
}

В случае как Foo, так и Bar нет значимого способа перемещения данных от одного к другому, поскольку оба они в конечном счете являются агрегатами типов POD - ни одна из их данных не является косвенной собственностью (указывает или ссылается на другие Память). Таким образом, в этих случаях перемещение выполняется как копия, а оригиналы (f, b) остаются неизменными после назначений в строках std::move().

Перемещение семантики может быть реализовано только с помощью динамически распределенной памяти или уникальных ресурсов.