Я только начинающий в операции перемещения в C ++ 11, так что играть с ним. Но нашел то, что я не в состоянии понять.
#include <iostream>
using namespace std;
class A{
public:
A(){cout << "default ctor" << endl;}
A(const string& str):_str{str}{cout << "parameter ctor" << endl;}
A(A&& obj):_str{std::move(obj._str)}{cout << "move ctor" << endl;}
A& operator =(A&& rhs){_str = std::move(rhs._str);cout << "move assignment operation" << endl; return *this;}
void print(){cout << _str << endl;}
private:
string _str;
};
int main(){
A a("rupesh yadav"); // parameter ctor
A b(std::move(a)); // move ctor
cout << "print a: ";
a.print(); // NOT printing --> CORRECT!!
cout << "print b: ";
b.print(); // printing --> CORRECT!!
b = std::move(a); // i don't know may be silly but still lets do it WHY NOT!!!, could be just mistake??
cout << "print a: ";
a.print(); // printing --> WRONG!!
cout << "print b: ";
b.print(); // NOT printing --> WRONG!!
}
Я ожидал, что b = std::move(a)
Операция будет вести себя иначе, потому что я применяю движение на объекте второй раз, но он копирует левый боковой объект б на правой стороне объекта , эту часть я не понимаю.
Или я сделал что-то не так в программировании.
Пожалуйста, помогите, если я делаю что-то не так в процессе перемещения.
РЕДАКТИРОВАТЬ: Я знаю, что это неопределенное поведение. Я сомневаюсь, что если я сделаю это снова, то это будет копирование с объекта для объекта б, и если я снова сделаю то же самое, то скопирую объект б для объекта ?
Следовательно, это копирование формы слева направо и справа налево, почему?
Вы не можете двинуться с одного и того же объекта дважды.
После того, как вы впервые переехали a
в b
, a
имел «допустимое, но неопределенное состояние» (не могу вспомнить точную терминологию). Затем вы попытались двигаться a
в b
снова! Теперь, черт возьми, вырвался (Я подозреваю, что внутренне указатели данных только что поменялись местами.)
Просто не делай этого. Я не вижу причин хотеть.
Ничто не мешает вам двинуться с объекта дважды. Стандартные объекты библиотеки должны быть оставлены в «допустимом, но неопределенном» состоянии при перемещении из. Единственное условие: «инварианты объекта соблюдаются, а операции над объектом ведут себя так, как указано для его типа». 17.3.28. Например, конструктор перемещения для std::string
говорит:
basic_string(const basic_string& str);
basic_string(basic_string&& str) noexcept;
2 Последствия: Строит объект класса
basic_string
как указано
в таблице [tab: strings.ctr.cpy]. Во втором классеstr
остается в
допустимое состояние с неопределенным значением.
Конструктор перемещения не имеет предварительных условий, и повторное перемещение из него не нарушит его инвариантов. Кроме того, поскольку это четко обозначено в стандарте, по определению это не неопределенное поведение. По упущению можно утверждать, что нарушая инварианты std::string
однако неопределенное поведение, но это приводит нас к:
Звонит operator<<
на std::string
запрещено? Описание от cppreference
говорит:
Ведет себя как
FormattedOutputFunction.
После построения и проверки сторожевого объекта, определяется
Выходной формат дополняется следующим образом:
Если
str.size()
не менее чемos.width()
, использует диапазон[str.begin(), str.end())
как естьВ противном случае, если
(os.flags() & ios_base::adjustfield) == ios_base::left
, местos.width()-str.size()
копии
os.fill()
символ после последовательности символовВ противном случае места
os.width()-str.size()
копииos.fill()
символ перед последовательностью символов
size()
, begin()
а также end()
не имеют предварительных условий, поэтому код совершенно безопасен.