Здравствуйте, lpd, Вы писали:
_>>_>>auto make_object(int p)
_>>{
_>> if(p<0) return big_object();
_>> big_object obj(p);
_>> prepare(obj);
_>> return obj;
_>>}
_>>auto obj=make_object(1024);
_>>
_>>Вот прямо в таком коде будет работать семантика перемещения (если конечно у big_object определены соответствующие методы). А теперь покажи свой более простой вариант, только чтобы он тоже был без копирования... )
lpd>Честно говоря, я не понял, какой в данном случае метод нужно объявить у big_object, чтобы он стал rvalue-ссылкой.
Естественно конструктор перемещение. Т.е. банально добавить в класс big_object метод "big_object(big_object&& о) {}" и всё, семантика перемещения заработает для данного классса.
lpd>Нужно вызвать move и вернуть big_object &&.
Нет, никаких move не требуется, компилятор сам всё сделает для return. Да, и кстати если убрать auto в моём коде, то на его месте будет просто big_object, без всяких ссылок. Никакие rvalue ссылки в самом коде использовать не надо, в этом и смысл данной техники — работаем со всеми объектами (включая и тяжёлые) просто как с обычными int'ми. )))
lpd>Но ты привел типичный случай, который решается элементарно:
lpd>lpd>big_object *make_object(int p)
lpd>{
lpd> if (p<0) return new big_object;
lpd> big_object *obj = new big_object(p);
lpd> prepare(obj);
lpd> return obj;
lpd>}
lpd>big_object *obj=make_object(1024);
lpd>...
lpd>delete obj;
lpd>
Ну так и какой код выглядит сложнее и объёмнее, мой или твой? ) Ты же заявлял, что код с применением семантики перемещения существенно усложняется...
lpd>Я не понимаю, это что, из управляемых языков пошло, что "всех new и delete нужно исключить"? В случае с move-семантикой вызывающий код получает локальный объект на стеке(?), который обречен быть локальным. В случае с указателем, его можно отдать разным обработчикам.
Вообще то это как раз в управляемых языках сплошные new (и неявные фоновые delete), которые и вызывают значительную часть тормозов языка. Вследствие введения дополнительного уровня косвенности, который не даёт нормально работать кэшу процессора. А как раз в современном C++ уходят от всего этого в сторону использования локальных переменных на стеке, которые являются самым эффективным инструментом. Да, а семантика перемещения как раз полностью решает проблему с передачей этого "локального" объекта куда-то ещё.
lpd>>>Давай конкретно: вот можешь описать случай с примером приложения и объекта, когда (бы) ты использовал move-семантику? хоть один?
_>>Вообще то там миллион сценариев. Более того, частенько даже древний код можно существенно ускорить без переписывания, если подключить (перекомпилировать с опцией C++11 или старше) ему семантику перемещения. Но если ты хочешь, то я покажу самый банальный пример с явным вызовом:
_>>_>>vector<big_object> vec;
_>>big_object obj;
_>>prepare(obj);
_>>vec.push_back(move(obj));
_>>
lpd>Такое всегда решалось динамическим созданием объекта и записью указателя в вектор. В твоем случае при реаллокации вектора все большие объекты будут копироваться. И опять же, на мой взгляд указатель удобнее для дальнейшей работы(нескольких обращений к нему без копирования).
И именно такой подход существенно убивает производительность, т.к. добавляет лишний уровень косвенности.
P.S. Ты только не обижайся, но что-то ты сейчас демонстрируешь отсутствие целого набора базовых знаний (и современного стандарта языка и вопросов оптимизации под современные процессоры), необходимых для хорошего специалиста по C++.