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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> C++11 move семантика, вопрос по примерам использования 
:(
    Опции темы
wladF
Дата 3.3.2013, 07:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 2.6.2009

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



Всем привет. 
В Интернете можно найти множество различных примеров использования данного нововведения в C++11, но практически все они сводятся к такому коду:
Код

class Container 
{
    Container(const Container& container) { /* обычный копирующий конструктор */ }

    Container(Container&& container) 
    {
        m_pData = container.m_pData;
        m_size = container.m_size;
    
        container.m_pData = nullptr;
        container.m_size = 0;
    }
    //..
};

int main() 
{
    Container a = {/*...*/};
    Container b(a); // медленно
    Container c(std::move(b)); // быстро, при этом b становится пустым    
}


Зачем нужна была здесь семантика переноса, если, грубо говоря, кроме как другого имени переменной мы не получили? 

Т.е. мы могли бы сделать, что-то типа:
Код

Container a = {/*...*/};
Container& c = a; // ну не нравится нам имя "а" ! теперь будет "c", и никакого копирования

Либо просто дальше использовать "a", не создавая других переменных.

Это сообщение отредактировал(а) wladF - 3.3.2013, 08:00
PM MAIL   Вверх
NoviceF
Дата 3.3.2013, 09:15 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Безотносительно данного примера, move семантика, например, даёт возможность использования умных указателей без подсчёта ссылок и с семантикой передачи владения (а-ля auto_prt) в контейнерах STL, пример - unique_ptr (с ограничениями на копирование).

http://stackoverflow.com/questions/2876641...stl-collections
PM MAIL   Вверх
JackYF
Дата 3.3.2013, 14:55 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

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



Цитата(wladF @  3.3.2013,  06:57 Найти цитируемый пост)
но практически все они сводятся к такому коду

Этот пример сам по себе не очень хорош, но его можно легко дополнить:

Код

std::vector< Container > xyz;
xyz.push_back(a); // медленно
xyz.push_back(std::move(a)); // быстро



--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
xvr
Дата 4.3.2013, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Мое IMHO - это было сделано для ускорения контейнелов, которые могут перемещать хранимые объекты в процессе своей жизни (std::vector например). Если vector делает resize, то без move семнтики его элементов, ему придется для каждого своего элемента позвать copy конструктор (для нового елемента), а потом деструктор (для старого), и то и другое может быть весьма дорого. При наличии move семантики будет вызван move constructor (что должно быть дешево) и деструктор для пустого элемента (что так же должно быть дешево)

PM MAIL   Вверх
volatile
Дата 5.3.2013, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Из FAQ'а Страуса. (вольный перевод)

Старый своп.
Код

template<class T> 
swap(T& a, T& b)  // "old style swap"
{
   T tmp(a);   // now we have two copies of a
   a = b;      // now we have two copies of b
   b = tmp;    // now we have two copies of tmp (aka a)
}

Теперь представим что мы вызываем его для двух строк, размером по мегабайту.
string str1 = "Очень длинная строка1 .....";
string str2 = "Очень длинная строка2 .....";
swap (str1, str2);
Здесь нам понадобицца дополнительная память в 1 мегабайт, плюс время для копирования 3 мегабайт.

Идеальный своп
Код

template<class T>
void swap(T& a, T& b)  // "perfect swap" (almost)
{
   T tmp = move(a);    // could invalidate a
   a = move(b);        // could invalidate b
   b = move(tmp);      // could invalidate tmp
}
Здесь произойдет мгновенный обмен, без дополнительных затрат памяти

PM MAIL   Вверх
Acer
Дата 8.3.2013, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

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



Цитата(JackYF @ 3.3.2013,  14:55)
Цитата(wladF @  3.3.2013,  06:57 Найти цитируемый пост)
но практически все они сводятся к такому коду

Этот пример сам по себе не очень хорош, но его можно легко дополнить:

Код

std::vector< Container > xyz;
xyz.push_back(a); // медленно
xyz.push_back(std::move(a)); // быстро

Для улучшения скорости этот пример бессмыслен, так как push_back тормозит, даже если сделать reserve()
Лучше уж так:
Код

std::vector<Container> xyz;
xyz.resize(num_items);
for (size_t i = 0; i < num_items; ++i)
    xyz[i] = std::move(a[i]);


Ps

Код

std::vector<Container> xyz;
xyz.resize(1);
xyz[0] = std::move(a);


Это сообщение отредактировал(а) Acer - 8.3.2013, 15:35
PM MAIL   Вверх
feodorv
Дата 8.3.2013, 14:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

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



Цитата(Acer @  8.3.2013,  15:32 Найти цитируемый пост)
for (size_t i = 0; i < num_items; ++i)
    xyz[i] = std::move(a);

Несколько раз подряд делать move для одной и той же переменной - это разве правильно?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Acer
Дата 8.3.2013, 15:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

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



Цитата(feodorv @ 8.3.2013,  14:56)
Цитата(Acer @  8.3.2013,  15:32 Найти цитируемый пост)
for (size_t i = 0; i < num_items; ++i)
    xyz[i] = std::move(a);

Несколько раз подряд делать move для одной и той же переменной - это разве правильно?

Нет. Ошибся. Пусть будет там a[i], например
PM MAIL   Вверх
volatile
Дата 8.3.2013, 23:23 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Acer @  8.3.2013,  14:32 Найти цитируемый пост)
Для улучшения скорости этот пример бессмыслен, так как push_back тормозит, даже если сделать reserve()
Лучше уж так:
std::vector<Container> xyz;
xyz.resize(num_items);
for (size_t i = 0; i < num_items; ++i)
    xyz[i] = std::move(a[i]);


При resize будут вызваны дефолтные конструкторы для добавляемых объектов.
(абсолютно лишняя операция, потому-что их сразу следом затрут)
При пуш-бэке дефолтные конструкторы вызваны не будут, а сразу объект будет перемещен на нужное место.
Сам пуш-бэк, при предварительном резерве, приктически ничо не стоит. 


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

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

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

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

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


 




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


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

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