Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> c++ x11 и rvalue reference 
V
    Опции темы
xTr1m
Дата 25.9.2013, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



День добрый. Просматривая стандарт, увидел такую классную штуку как rvalue reference. Захотел применить, допустим, есть код
Код

CString GetText()
{
CString str = "some big string";
return str;
}

void main()
{
CString str = GetText();
}

то есть проблема в том, что мы выделяем память память под большую строку, потом возвращаем ее из функции, но при этом вызывается конструктор копирования, который снова выделяет память и удаляет старую. Как я понимаю, тут можно использовать механику конструктора перемещения, скорее всего, используя rvalue. Но у меня не получилось. Пробовал так
Код

void main()
{
CString &&str = GetText();
}

ну и еще несколькими дурацкими способами, но не получилось. Конструктор копирования все равно вызывается. Может я что-то не так понял про r-value ref? Спасибо.
PM MAIL WWW ICQ   Вверх
vinter
Дата 25.9.2013, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Покажите CString. У него есть конструктор CString(CString&& rhs)? Если да, то какой компилятор?

Добавлено через 1 минуту и 13 секунд
Цитата

Пробовал так

Знаете правило: никогда не брать не-константную ссылку на объект возвращенный из функции? rvalue reference в этом смысле ничем не отличается. Так что так писать весьма вредно.


--------------------
Мой блог
PM MAIL WWW   Вверх
azesmcar
Дата 25.9.2013, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



используй std::move

Код

#include <iostream>
#include <string>

class C
{
public:
    C()
    {
     s_ = "hello world";
    };
    C(C&& c)
    {
     s_ = std::move(c.s_);
    }
    const char *c_str() const
    {
     return s_.c_str();
    }
private:
    std::string s_;
};

int main()
{
    C c1;
    C c2 = std::move(c1);

    std::cout << c2.c_str() << std::endl;
}


Это сообщение отредактировал(а) azesmcar - 26.9.2013, 10:05
PM   Вверх
baldina
Дата 25.9.2013, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



xTr1m, ничего вы таким образом не выиграете, даже наоборот. в вашем случае будет NRVO работать. 
rvalue reference хорошо применять там, где допускается семантика переноса, не очевидная компилятору (т.е. везде, где не идет речь о создании и возврате временного объекта).
PM MAIL   Вверх
xTr1m
Дата 25.9.2013, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



По поводу правила  никогда не брать не-константную ссылку на объект возвращенный из функции это я понимаю, но как я понял rvalue как раз для этого, нет? То есть, был некий объект в функции и  мы хотим его вернуть. Понятно, что возвращать обычную ссылку нельзя, а rvalue не для этого был создан? То есть мы переносим объект из функции в другой объект без копирования, а переносом (указателя или что там еще).

CString - это из MFC и там конечно же нет такого. Делать обертку к нему? Не знаю насколько это будет целесообразно. Может посмотрю в сторону std::string, может там конструктор перемещения определен. 

За пример с std::move спасибо. Интересно, а можно использовать его с CString? Но это опять же обертку делать. А вообще как решаются такие задачи. Задача: в функции генерируется большая строка, хочу вернуть ее без перевыделения памяти.
PM MAIL WWW ICQ   Вверх
vinter
Дата 25.9.2013, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



azesmcar, убери && после C. Твой код конструктор перемещения не вызывает, а лишь создаёт rvalue ссылку.


--------------------
Мой блог
PM MAIL WWW   Вверх
azesmcar
Дата 25.9.2013, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



А вообще можно реализовать Copy-on-write.
PM   Вверх
xTr1m
Дата 25.9.2013, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



Сейчас попробовал сделать так
Код

std::string GetText()
{
std::string str = "some big string";
return str;
}
void main()
{
std::string str = GetText();
}

и тут сразу вызывается конструктор перемещения. попробую засечь насколько быстрее получается.
PM MAIL WWW ICQ   Вверх
vinter
Дата 25.9.2013, 18:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата

это я понимаю, но как я понял rvalue как раз для этого, нет? То есть, был некий объект в функции и  мы хотим его вернуть. Понятно, что возвращать обычную ссылку нельзя, а rvalue не для этого был создан?

Не совсем. Rvalue reference никогда нельзя возвращать из функции. Это моё утверждение не совсем верно, но пока полностью не проникнитесь rvalue ссылками лучше думать именно так. Т.к. возврщать ссылку на rvalue нужно в очень ограниченном числе случаев. Возвращать нужно просто по значению. Для использования семантики перемещений в возвращаемом объекте код менять не нужно, нужно просто добавить конструктор перемещения  в тот класс, перемещения которго Вы желаете.
Цитата

CString - это из MFC и там конечно же нет такого. Делать обертку к нему? Не знаю насколько это будет целесообразно.

Тем не менее это единственный выход. Другого нет.
Цитата

Может посмотрю в сторону std::string, может там конструктор перемещения определен. 

Да, все библиотечные классы имеют конструктор перемещения(для которых целесообразно, по крайней мере)

Я писал статью про rvalue references. Посмотрите, может проясните что-нибудь для себя.


--------------------
Мой блог
PM MAIL WWW   Вверх
xTr1m
Дата 25.9.2013, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



Большое спасибо, прочту.
PM MAIL WWW ICQ   Вверх
xTr1m
Дата 25.9.2013, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



Очень странно, написал две функции
Код

std::string GetText()
{
    std::string str("adsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsa");

    return str;
}

CString GetTextMfc()
{
    CString str("adsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsaadsa");

    return str;
}


и прогнал так
Код

for(int i=0; i<10000; ++i)
{
    std::string str = GetText();
    //CString strMfc = GetTextMfc(); // потом наоборот
}

и время выполнения в release одинаково! Хотя в одном случае идет копирование (mfc CString), а в другом перемещение (std::string). Тогда в чем выигрыш в семантике перемещения?
PM MAIL WWW ICQ   Вверх
vinter
Дата 25.9.2013, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



как выше указал(а) baldina работает NRVO, т.е. ни конструктор копирования, ни конструктор перемещения не вызываются вообще. NRVO быстрее и, соответственно, срабатывает когда можно. 
Конструктор перемещения нужен для всех остальных случаев.

А может весь код вообще выброшен компилятором как бесполезный. Всё зависит от агрессивности оптимизатора

Это сообщение отредактировал(а) vinter - 25.9.2013, 19:19


--------------------
Мой блог
PM MAIL WWW   Вверх
xTr1m
Дата 25.9.2013, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



То есть NRVO применятеся только в релизе? (спрашиваю, так как в дебаге смотрел и вызывались конструктор копирования и перемещения)

Добавлено через 3 минуты и 16 секунд
То есть получается, что я так ничего несоптимизирую (имею в виду возврат временного объекта из функции). А можно какой-нибудь пример, где применяется семантика перемещения без временного объекта. Я пока читал про std::thread понял, что для его передачи между функциями, например, используется как раз std::move. А где еще?
PM MAIL WWW ICQ   Вверх
baldina
Дата 25.9.2013, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(xTr1m @  25.9.2013,  19:33 Найти цитируемый пост)
То есть NRVO применятеся только в релизе?

да, потому что в debug отключена оптимизация

Цитата(xTr1m @  25.9.2013,  19:33 Найти цитируемый пост)
какой-нибудь пример

Код

class String {
  char *buf;
  size_t size;

  public:
     ...

     String (String&& o) : buf(std::move(o.buf), size(std::move(o.size) {}

     ~String () { delete buf; }
};


Это сообщение отредактировал(а) baldina - 25.9.2013, 20:22
PM MAIL   Вверх
vinter
Дата 25.9.2013, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата

То есть NRVO применятеся только в релизе?

NRVO это дело оптимизатора. Оптимизация, как правило, в дебаге выключена. RVO и NRVO не всегда применимы. Тогда идёт выигрыш от перемещения. 
std::unique_ptr еще без перемещения не работает. Применяется везде где нужно, где есть объект который можно переместить и там где есть объект который только и можно перемещать.
Многие отказываются от передачи по константной ссылке аргументов функции в пользу аргументов по значению, когда передаются типы с перемещающим конструктором. Вариантов масса. Просто искусственно не нужно использовать, я считаю. Ну и взять в привычку добавлять конструктор перемещения для всех своих классов у которых есть явный конструктор копирования.

Это сообщение отредактировал(а) vinter - 25.9.2013, 20:16


--------------------
Мой блог
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0644 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.