![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| xTr1m |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 692 Регистрация: 9.2.2005 Где: Москва Репутация: 1 Всего: 1 |
День добрый. Просматривая стандарт, увидел такую классную штуку как rvalue reference. Захотел применить, допустим, есть код
то есть проблема в том, что мы выделяем память память под большую строку, потом возвращаем ее из функции, но при этом вызывается конструктор копирования, который снова выделяет память и удаляет старую. Как я понимаю, тут можно использовать механику конструктора перемещения, скорее всего, используя rvalue. Но у меня не получилось. Пробовал так
ну и еще несколькими дурацкими способами, но не получилось. Конструктор копирования все равно вызывается. Может я что-то не так понял про r-value ref? Спасибо. |
||||
|
|||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
Покажите CString. У него есть конструктор CString(CString&& rhs)? Если да, то какой компилятор?
Добавлено через 1 минуту и 13 секунд
Знаете правило: никогда не брать не-константную ссылку на объект возвращенный из функции? rvalue reference в этом смысле ничем не отличается. Так что так писать весьма вредно. |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
используй std::move
Это сообщение отредактировал(а) azesmcar - 26.9.2013, 10:05 |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
xTr1m, ничего вы таким образом не выиграете, даже наоборот. в вашем случае будет NRVO работать.
rvalue reference хорошо применять там, где допускается семантика переноса, не очевидная компилятору (т.е. везде, где не идет речь о создании и возврате временного объекта). |
|||
|
||||
| xTr1m |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 692 Регистрация: 9.2.2005 Где: Москва Репутация: 1 Всего: 1 |
По поводу правила никогда не брать не-константную ссылку на объект возвращенный из функции это я понимаю, но как я понял rvalue как раз для этого, нет? То есть, был некий объект в функции и мы хотим его вернуть. Понятно, что возвращать обычную ссылку нельзя, а rvalue не для этого был создан? То есть мы переносим объект из функции в другой объект без копирования, а переносом (указателя или что там еще).
CString - это из MFC и там конечно же нет такого. Делать обертку к нему? Не знаю насколько это будет целесообразно. Может посмотрю в сторону std::string, может там конструктор перемещения определен. За пример с std::move спасибо. Интересно, а можно использовать его с CString? Но это опять же обертку делать. А вообще как решаются такие задачи. Задача: в функции генерируется большая строка, хочу вернуть ее без перевыделения памяти. |
|||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
azesmcar, убери && после C. Твой код конструктор перемещения не вызывает, а лишь создаёт rvalue ссылку.
|
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
А вообще можно реализовать Copy-on-write.
|
|||
|
||||
| xTr1m |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 692 Регистрация: 9.2.2005 Где: Москва Репутация: 1 Всего: 1 |
Сейчас попробовал сделать так
и тут сразу вызывается конструктор перемещения. попробую засечь насколько быстрее получается. |
|||
|
||||
| vinter |
|
||||||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
Не совсем. Rvalue reference никогда нельзя возвращать из функции. Это моё утверждение не совсем верно, но пока полностью не проникнитесь rvalue ссылками лучше думать именно так. Т.к. возврщать ссылку на rvalue нужно в очень ограниченном числе случаев. Возвращать нужно просто по значению. Для использования семантики перемещений в возвращаемом объекте код менять не нужно, нужно просто добавить конструктор перемещения в тот класс, перемещения которго Вы желаете.
Тем не менее это единственный выход. Другого нет.
Да, все библиотечные классы имеют конструктор перемещения(для которых целесообразно, по крайней мере) Я писал статью про rvalue references. Посмотрите, может проясните что-нибудь для себя. |
||||||
|
|||||||
| xTr1m |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 692 Регистрация: 9.2.2005 Где: Москва Репутация: 1 Всего: 1 |
Большое спасибо, прочту.
|
|||
|
||||
| xTr1m |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 692 Регистрация: 9.2.2005 Где: Москва Репутация: 1 Всего: 1 |
Очень странно, написал две функции
и прогнал так
и время выполнения в release одинаково! Хотя в одном случае идет копирование (mfc CString), а в другом перемещение (std::string). Тогда в чем выигрыш в семантике перемещения? |
||||
|
|||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
как выше указал(а) baldina работает NRVO, т.е. ни конструктор копирования, ни конструктор перемещения не вызываются вообще. NRVO быстрее и, соответственно, срабатывает когда можно.
Конструктор перемещения нужен для всех остальных случаев. А может весь код вообще выброшен компилятором как бесполезный. Всё зависит от агрессивности оптимизатора Это сообщение отредактировал(а) vinter - 25.9.2013, 19:19 |
|||
|
||||
| xTr1m |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 692 Регистрация: 9.2.2005 Где: Москва Репутация: 1 Всего: 1 |
То есть NRVO применятеся только в релизе? (спрашиваю, так как в дебаге смотрел и вызывались конструктор копирования и перемещения)
Добавлено через 3 минуты и 16 секунд То есть получается, что я так ничего несоптимизирую (имею в виду возврат временного объекта из функции). А можно какой-нибудь пример, где применяется семантика перемещения без временного объекта. Я пока читал про std::thread понял, что для его передачи между функциями, например, используется как раз std::move. А где еще? |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
да, потому что в debug отключена оптимизация
Это сообщение отредактировал(а) baldina - 25.9.2013, 20:22 |
|||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
NRVO это дело оптимизатора. Оптимизация, как правило, в дебаге выключена. RVO и NRVO не всегда применимы. Тогда идёт выигрыш от перемещения. std::unique_ptr еще без перемещения не работает. Применяется везде где нужно, где есть объект который можно переместить и там где есть объект который только и можно перемещать. Многие отказываются от передачи по константной ссылке аргументов функции в пользу аргументов по значению, когда передаются типы с перемещающим конструктором. Вариантов масса. Просто искусственно не нужно использовать, я считаю. Ну и взять в привычку добавлять конструктор перемещения для всех своих классов у которых есть явный конструктор копирования. Это сообщение отредактировал(а) vinter - 25.9.2013, 20:16 |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |