std :: move против std :: auto_ptr? - PullRequest
5 голосов
/ 11 декабря 2011

Что я могу сделать с 'move' (ссылки на r-значение) в C ++ 11, что я не могу сделать с std::auto_ptr? (Насколько я понимаю, это разные реализации одной идеи.)

И снова старый вопрос: std::auto_ptr такой плохой компонент?

Ответы [ 5 ]

16 голосов
/ 11 декабря 2011

C ++ 98/03 не имеет понятия действительно «подвижных» классов.auto_ptr - это класс с семантикой передачи при копировании, то есть при создании копии содержимое оригинала изменяется (обратите внимание на конструктор копирования с неконстантным аргументом!).Это плохо.Такой класс нельзя использовать в стандартных контейнерах.

C ++ 11 вводит концепцию действительно подвижных классов благодаря недавно добавленному понятию ссылок rvalue.Новый unique_ptr, который полностью заменяет auto_ptr, больше вообще не копируется, а вместо этого подвижный .Все стандартные контейнеры были обновлены, чтобы попытаться переместить объекты, если это возможно, поэтому теперь можно хранить объекты только для перемещения в стандартных контейнерах.Другими примерами объектов, которые являются только подвижными, но не копируемыми, являются мьютексы, блокировки, потоки и iostreams.

Чтобы вбить точку, сравните гипотетический, неработающий фрагмент кода C ++ 98 с соответствующим C ++11 код:

std::auto_ptr<Foo> p1(new Foo);
std::vector< std::auto_ptr<Foo> > v1;
//v1.push_back(p1);  // eeww, what is the state of p1 now? ERROR

std::unique_ptr<Foo> p2(new Foo);
std::vector<std::unique_ptr<Foo>> v2;
//v2.push_back(p2);          // Error, copying is simply not allowed
v2.push_back(std::move(p2)); // explicit; mustn't read p2 after moving it
v2.emplace_back(new Foo);    // even better ;-)
5 голосов
/ 11 декабря 2011

Проблема с std::auto_ptr состоит в том, что он имеет операции копирования, которые работают как операции перемещения.Поэтому алгоритмы, которые работают с операциями копирования, могут работать на auto_ptr, но они не ведут себя должным образом, так как скопированные из объектов изменились.Таким образом, auto_ptr нельзя использовать с контейнерами STL, однако код, который пытается это сделать, скомпилируется, но не работает во время выполнения.

std::unique_ptr, с другой стороны, не имеет операций копирования, но только подвижный вместо.Поэтому алгоритмы, которые копируют std::unique_ptr, не будут компилироваться, когда они должны работать на std::unique_ptr.Если что-то использует операции перемещения, оно не ожидает, что источник операции перемещения останется прежним, поэтому здесь нет путаницы.

Таким образом, в основном все сводится к операциям, работающим так, как ожидается для объекта C ++ (или нет).

2 голосов
/ 11 декабря 2011

Что я могу сделать с 'move' (ссылки на r-значение) в C ++ 11, что я не могу с помощью std :: auto_ptr?

Самое важное преимущество move, unique_ptr и т. Д. Над auto_ptr - это то, что вы не можете сделать, но может с auto_ptr.

Эта ссылка объясняет обоснование для комитета осудить auto_ptr. В нем содержится такой вывод:

Вывод:

Не следует переходить от lvalues ​​с использованием синтаксиса копирования. Другой синтаксис для вместо этого следует использовать перемещение. В противном случае общий код может начать движение, когда копия была предназначена.

Подробнее о том, как был сделан этот вывод, читайте по ссылке .

2 голосов
/ 11 декабря 2011

auto_ptr принципиально сломан, а ссылки на rvalue - нет.Это так просто.

2 голосов
/ 11 декабря 2011

Одно большое отличие состоит в том, что ссылки на rvalue (и различные оптимизации перемещений) автоматически выводятся / вычитаются из контекста вызова, тогда как вам нужно создать auto_ptr вручную на сайте вызова.

...