Что продолжается после использования std:: move С++ 11

После использования std:: move в переменной, которая может быть полем в классе, например:

class A {
  public:
    vector<string>&& stealVector() {
      return std::move(myVector);
    }
    void recreateMyVector() {
    }
  private:
    vector<string> myVector;        
};

Как бы я воссоздал вектор, как ясный? Что осталось в myVector после std:: move?

Ответ 1

Общая мантра состоит в том, что переменная, которая была "перемещена из", находится в действительном, но неуказанном состоянии. Это означает, что можно уничтожить и назначить переменной, но ничего больше.

(Степанов называет это "частично сформированным", я считаю, это хороший термин.)


Чтобы быть ясным, это не строгое правило; скорее, это руководство о том, как думать о перемещении: после того, как вы переходите от чего-то, вы больше не должны использовать оригинальный объект. Любая попытка сделать что-то нетривиальным с исходным объектом (кроме присвоения ему или уничтожить его) должна быть тщательно продуманной и обоснованной.

Однако в каждом конкретном случае могут быть дополнительные операции, которые имеют смысл на перемещенном объекте, и, возможно, вы захотите воспользоваться этими преимуществами. Например:

  • В стандартных библиотечных контейнерах описываются предварительные условия для их операций; операции без pre & shy, условия в порядке. Единственные полезные, которые приходят на ум, - это clear() и, возможно, swap() (но предпочитают назначение, а не свопинг). Существуют другие операции без предварительных условий, например size(), но, следуя приведенным выше рассуждениям, вы не должны иметь деловые запросы после размера объекта, который вы только что сказали, что вам больше не нужно.

  • unique_ptr<T, D> гарантирует, что после перемещения из него это значение равно null, которое вы можете использовать в ситуации, когда право собственности принимается условно:

    std::unique_ptr<T> resource(new T);
    std::vector<std::function<int(std::unique_ptr<T> &)> handlers = /* ... */;
    
    for (auto const & f : handlers)
    {
        int result = f(resource);
        if (!resource) { return result; }
    }
    

    Обработчик выглядит следующим образом:

    int foo_handler(std::unique_ptr<T> & p)
    { 
        if (some_condition))
        {
            another_container.remember(std::move(p));
            return another_container.state();
        }
        return 0;
    }
    

    Было бы возможно в общем случае, чтобы обработчик возвращал какое-то другое состояние, которое indi & shy; указывает, было ли оно владением от уникального указателя, но так как стандартный фактически guaran & shy; тройники, которые перемещаются из уникального указателя, оставляют его как null, мы можем использовать это для передачи этой информации в уникальный указатель.

Ответ 2

Переместите вектор-член к локальному вектору, очистите член, верните значение local по значению.

std::vector<string> stealVector() {
    auto ret = std::move(myVector);
    myVector.clear();
    return ret;
}

Ответ 3

Что осталось в myVector после std:: move?

std::move не перемещается, это просто бросок. Может случиться, что myVector не поврежден после вызова stealVector(); см. вывод первого a.show() в приведенном ниже примере кода. (Да, это глупый, но действительный код.)

Если кишки myVector действительно украдены (см. b = a.stealVector(); в примере кода), он будет в действительном, но неуказанном состоянии. Тем не менее, он должен быть назначаемым и разрушаемым; в случае std::vector вы можете спокойно позвонить clear() и swap(). Вы действительно не должны делать никаких других предположений относительно состояния вектора.

Как бы я воссоздал вектор, как ясный?

Один из вариантов - просто называть clear() на нем. Тогда вы точно знаете его состояние.


Пример кода:

#include <initializer_list>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class A {
  public:
    A(initializer_list<string> il) : myVector(il) { }
    void show() {
      if (myVector.empty())
        cout << "(empty)";
      for (const string& s : myVector)
        cout << s << "  ";
      cout << endl;
    }
    vector<string>&& stealVector() {
      return std::move(myVector);
    }
  private:
    vector<string> myVector;        
};

int main() {
  A a({"a", "b", "c"});
  a.stealVector();
  a.show();
  vector<string> b{"1", "2", "3"};
  b = a.stealVector();
  a.show();
}

Это выводит на мой компьютер следующие данные:

a b c
(пусто)