Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
#1

Что такое move семантика? - C++

23.11.2014, 19:22. Просмотров 1220. Ответов 17
Метки нет (Все метки)

Что такое move семантика?

Добавлено через 6 минут
Я правильно понимаю, что mov присваивание перемещает правый операнд на место левого? И как его писать?
Пусть есть некий класс, чьи объекты имеют указатель на родителя и указатель на массив потомков.
C++
1
2
3
4
5
6
7
8
class A
{
 A *Parent;
 A *Children;
 size_t Count;
 public:
  A &operator = (A &a);
};
. Как написать реализацию move присваивания для этого класса?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.11.2014, 19:22
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Что такое move семантика? (C++):

move семантика - C++
Сейчас стало появляться нечто вроде такого: class X { public: X (const X& lvalue); // copy constructor X (X&& rvalue);...

Move семантика (класс полиномов) - C++
Доброго времени суток. Пишу простенький класс полиномов, в котором есть единственное приватное поле - это map. Вот думаю надо ли писать...

Что такое файловый буфер? Что такое режим (модификатор) доступа, при работе с файлами? - C++
Что такое файловый буфер? Что такое режим (модификатор) доступа, при работе с файлами?

Что такое рекурсивный тип данных? Что такое конструкция рекурсивного типа? - C++
Что такое рекурсивный тип данных? Что такое конструкция рекурсивного типа?

Что такое хэндлер файла? Что такое файловый указатель? - C++
Что такое хэндлер файла? Что такое файловый указатель?

Что такое заголовочный файл? Что такое файл исходного кода? Рассмотрите назначение каждого из них - C++
Что такое заголовочный файл? Что такое файл исходного кода? Рассмотрите назначение каждого из них пожалуйста.

17
Pancir
57 / 44 / 10
Регистрация: 16.09.2014
Сообщений: 124
23.11.2014, 19:28 #2
Вот реально странно, вроде опытный человек на форуме, а задать свой вопрос сперва у гугля не догадывается, там уже все ответы есть.
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
23.11.2014, 19:29  [ТС] #3
То есть A &operator = (A &&a);
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
23.11.2014, 19:33 #4
Цитата Сообщение от taras atavin Посмотреть сообщение
Как написать реализацию move присваивания для этого класса?
Через swap.
0
Nosey
1349 / 400 / 107
Регистрация: 22.10.2014
Сообщений: 863
Завершенные тесты: 2
23.11.2014, 19:34 #5
Наверное так :
C++
1
2
3
4
5
6
7
8
9
10
11
12
class A
{
 A *Parent;
 A *Children;
 size_t Count;
 public:
  A &operator = (A &&a){
std::swap(Parent,a.Parent);
std::swap(Children,a.Children);
Count = a.Count;
}
};
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
23.11.2014, 20:09  [ТС] #6
Цитата Сообщение от Pancir Посмотреть сообщение
а задать свой вопрос сперва у гугля не догадывается, там уже все ответы есть.
Догадался.

Добавлено через 15 минут
C++
1
2
3
4
5
6
7
8
class TDirectory
{
 std::wstring                  Name;
 TDirectory                   *Parent;
 TDirectory                   *Children;
 size_t                        ChildrenCount;
 ...
};
C++
1
2
3
4
5
6
7
8
9
10
        TDirectory                     &
       TDirectory    ::                 operator =                                            (      TDirectory     &&Directory       )
{
 Name         =Directory.Name;
 Parent       =Directory.Parent;
 Children     =Directory.Children
 ChildrenCount=Directory.ChildrenCount;
 Directory.Children     =NULL;
 Directory.ChildrenCount=0;
}
,
на строку
C++
1
*Target=*Source;
пишет
C++
1
error: use of deleted function 'TDirectory& TDirectory::operator=(const TDirectory&)'|
. Я не операционную систему пишу, у меня внутри документа будут каталоги, но с точки зрения операционной системы это будет ровно один файл и каталогов внутри она не увидит.
C++
1
2
 TDirectory *Source;
 TDirectory *Target;
.
0
Nosey
1349 / 400 / 107
Регистрация: 22.10.2014
Сообщений: 863
Завершенные тесты: 2
23.11.2014, 20:13 #7
taras atavin,
Значит *Source не есть rvalue, и мув присваивание не вызывается, а вызывается обычное, которого судя по ошибке нет ))
Либо сами кастуем к rvalue, либо пишем обычное присваивание.
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
3945 / 2169 / 553
Регистрация: 18.10.2014
Сообщений: 3,783
23.11.2014, 21:00 #8
Цитата Сообщение от taras atavin Посмотреть сообщение
пишет
error: use of deleted function 'TDirectory& TDirectory::operator=(const TDirectory&)'|
Неформально выражаясь, компилятор будет сам вызывать мув оператор присваивания только тогда, когда компилятор уверен, что объект в правой части - не жилец, т.е. будет уничтожен [почти] сразу после присваивания. В частности, присваивание из временных объектов будет идти по мув оператору

C++
1
2
3
TDirectory *target;
...
*target = TDirectory();
Если же объект в правой части не уничтожается сразу после присваивания, то мув автоматически делаться не будет. Его надо специально заказывать

C++
1
2
3
TDirectory *target, *source;
...
*target = std::move(*source);
1
hoggy
6701 / 2883 / 494
Регистрация: 15.11.2014
Сообщений: 6,480
Завершенные тесты: 1
23.11.2014, 21:46 #9
Цитата Сообщение от taras atavin Посмотреть сообщение
Что такое move семантика?
Самое главное, что нужно понять: вы можете писать методы, которые различают "обычные объекты" (lvalue) и "временные" (rvalue)

Что такое временный объект? Это объект, который гарантированно не жилец.
А значит, в некоторых случаях, можно его опустошить, и тем самым оптимизировать создание объекта по его прототипу.

Покажу на примере:

http://rextester.com/JCQZS64854

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
using namespace std;
 
struct sample
{
    int* data;
    
    ~sample()
    {
        if(data)
            cout<<"delete object("<<*data<<")\n";
        else
            cout<<"delete empty object\n";
            
        
        delete data;
    }
    
    sample(const int v)
        : data( new int(v) )
    { cout<<"ctor("<<*data<<")\n"; }
    
    sample():data(nullptr) { cout<<"ctor\n"; }
    sample(const sample&)  { cout<<"copy\n"; }
    sample(sample&&     )  { cout<<"move\n"; }
    
    sample& operator=(const sample& rhs)
    {
        cout<<"copy operator=\n";
        data = new int(*rhs.data);
        return *this;
    }
    
    sample& operator=(sample&& rhs)
    {
        cout<<"move operator=\n";
        
        data = rhs.data;
        rhs.data = nullptr;
        return *this;
    }
};
 
sample foo()
{
    sample s(10);
    return s;
}
 
int main()
{
    std::cout << "Hello, world!\n";
    
    sample s;
    s = foo();
}
sample держит внутри себя указатель на данные в куче.

Если мы попытается сделать копию объекта - мы не можем просто скопировать указатель.
Мы должны сделать глубокую копию данных, или получим двойное удаление в диструкторе.

Но если мы заранее знаем, что создание объекта происходит по прототипу временного объекта, то мы можем "опустошить" временный объект: не делая глубокой копии данных, просто скопировать указатель, занулив его у временного объекта.

Таким образом осуществляются оптимизации создания объектов без необходимости выполнять глубокую копию.

--------------

Иногда бывают случаи, когда объект по факту не является временным.
Но вы совершенно уверены, что объект вам больше не нужен.

И тогда, вы можете использовать std::move, что бы явно подчеркнуть, что этот объект можно опустошать.
2
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
24.11.2014, 04:25  [ТС] #10
Цитата Сообщение от hoggy Посмотреть сообщение
И тогда, вы можете использовать std::move, что бы явно подчеркнуть, что этот объект можно опустошать.
Как?
0
0x10
2479 / 1654 / 248
Регистрация: 24.11.2012
Сообщений: 4,099
24.11.2014, 04:27 #11
Цитата Сообщение от taras atavin Посмотреть сообщение
Как?
Пост 8, последняя строчка.
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
24.11.2014, 04:30  [ТС] #12
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
TDirectory *target, *source; ... *target = std::move(*source);
Здесь нужен конструктор перемещения, или достаточно присваивания?
0
Croessmah
Ушел
Эксперт CЭксперт С++
13554 / 7705 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
24.11.2014, 04:32 #13
Цитата Сообщение от taras atavin Посмотреть сообщение
Что такое move семантика?
вкратце: Семантика перемещения и perfect forwarding(правильная передача)
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
3945 / 2169 / 553
Регистрация: 18.10.2014
Сообщений: 3,783
24.11.2014, 05:20 #14
Цитата Сообщение от taras atavin Посмотреть сообщение
Здесь нужен конструктор перемещения, или достаточно присваивания?
Здесь - именно перемещающий оператор присваивания.
1
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
23.12.2014, 07:31  [ТС] #15
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Здесь - именно перемещающий оператор присваивания.
Это понятно. А при его наличии перемещающий конструктор нужен?
0
23.12.2014, 07:31
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.12.2014, 07:31
Привет! Вот еще темы с ответами:

Vector::swap и std::move - что эффективнее? - C++
Пусть имеется пустой вектор A и заполненный некими данными вектор B. Тогда какой из методов более эффективный: A.swap(B); A =...

Что происходит когда std::move применяется для int? - C++
Мне, вроде бы, понятно как работает std::move() на классах типа string. Но мне непонятно что будет в данном случаи. #include &lt;iostream&gt; ...

Объяснить что такое "раздельная компиляция", что такое "интерфейс класса" и "реализация класса" на примере - C++
Есть класс, содержащий объекты и конструктор. Конструктор объявляется в одном из cpp файлов(их несколько). Можно ли, как-то, использовать...

Что такое перегрузка оператора? Что у меня в коде за ошибка? - C++
Что же я написал?? Что оно не компилится? Что значит error C2275: Superclass: недопустимое использование этого типа в качестве выражения ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru