Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915

Десятая попытка понять std::move

14.07.2023, 17:11. Показов 1604. Ответов 9

Студворк — интернет-сервис помощи студентам
Здравствуйте,

Пытаюсь понять в 10ый раз, что же делает std::move и как работает.
Концепцию rvalue ссылок я так понять и не смог, так как безнадежно туп.

Но вот на таком простом примере:


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
struct my_struct_value
{
int int_;
double double_;
float float_;
size_t size_t_;
char* char_p;
wchar_t* wchar_t_p;
 
 
 
my_struct_value() = default;
 
 
my_struct_value(my_struct_value&& other) noexcept
{
int_ = other.int_;
double_ = other.double_;
float_ = other.float_;
size_t_ = other.size_t_;
char_p = std::move(other.char_p);
wchar_t_p = other.wchar_t_p;
other.char_p = nullptr;
other.wchar_t_p = nullptr;
}
 
};
 
int main()
{
 
my_struct_value my_struct_value_;
 
my_struct_value_.char_p = (char*)"Hello HELL";
 
 
std::vector<my_struct_value>vector;
 
vectr.push_back(std::move(my_struct_value_));
 
 
return 0;
}

Что будет после вызова std::move(my_struct_value_) ?

В векторе выделится память и просто построится объект структуры ?

Если да, то чем это отличается от emplace_back() ?

Ведь копирование все равно произошло или нет ?

То есть я имею виду, когда я создал объект my_struct_value_ - он в условной "куче" стал занимать место, когда я сделал push_back в векторе и std::move(my_struct_value_), то по простому вызвался memcpy() и байты из памяти которая выделена под my_struct_value_ были просто перекопированы в новую память, которая выделилась в векторе, и сама память под my_struct_value_ никуда не делась, просто часть или все поля структуры занялись и я теперь не могу к ним обращается.

Или же происходит что то другое ?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
14.07.2023, 17:11
Ответы с готовыми решениями:

std::move
Есть такой код: int main() { int lol = 2; int&amp;&amp; p1 = move(lol); //здесь все ок int&amp;&amp; grind =...

std::move()
Здравствуйте! Хочу разобраться с функцией std::move(). Код, приведенный ниже работает как и ожидается, значение в переменной str...

std::move в Си
Вот какую бы статью про std::move не начинаешь читать в попытке понять, как же работает и в каких случаях нужен std::move, везде пишут, что...

9
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,231
14.07.2023, 17:33
Лучший ответ Сообщение было отмечено Optimus11 как решение

Решение

Цитата Сообщение от Optimus11 Посмотреть сообщение
Что будет после вызова std::move(my_struct_value_) ?
Непосредственно после вызова std::move(my_struct_value_) не будет ничего. std::move - это просто static_cast. Он ничего физически не делает.

Результатом этого std::move будет безымянное my_struct_value&&.

Далее overload resolution выберет соответствующую версию push_back и вызовет ее. А она уже внутри себя при конструировании нового элемента вектора снова сделает std::move. В результате этого, overload resolution для конструирования нового элемента вектора выберет ваш конструктор my_struct_value(my_struct_value&& other).

Вот и все.

Цитата Сообщение от Optimus11 Посмотреть сообщение
В векторе выделится память и просто построится объект структуры ?
Разумеется.

Цитата Сообщение от Optimus11 Посмотреть сообщение
Если да, то чем это отличается от emplace_back() ?
Интерфейсом. А что здесь делает этот вопрос? Он не имеет отношения к теме std::move.

Цитата Сообщение от Optimus11 Посмотреть сообщение
Ведь копирование все равно произошло или нет ?
Произошел вызов конструктора my_struct_value(my_struct_value&& other) для конструирования нового элемента. На этом роль std::move закончилась.

А дальше произойдет то, что вы сами руками написали внутри my_struct_value(my_struct_value&& other). Напишете копирование - будет копирование. Да, произошло копирование, потому что вы сами руками написали там копирование.

Сколько раз уже дылдонили: в ядре языка С++ нет никакой "семантики перемещения". Никакого "перемещения" язык сам по себе делать не умеет. В ядре языка есть только &&-ссылки и правила overload resolution для них. Все остальное, т.е. "семантику перемещения", вам придется писать вручную. Что напишете - то и получите. Вы написали "семантику перемещения" которая делает копирование - вот и получилось копирование.

Цитата Сообщение от Optimus11 Посмотреть сообщение
То есть я имею виду, когда я создал объект my_struct_value_ - он в условной "куче" стал занимать место, когда я сделал push_back в векторе и std::move(my_struct_value_), то по простому вызвался memcpy() и байты из памяти которая выделена под my_struct_value_ были просто перекопированы в новую память, которая выделилась в векторе,
Нет, ничего подобного не происходит. Какое еще memcpy? Откуда вы взяли такую чушь? Где у вас в коде memcpy?

Цитата Сообщение от Optimus11 Посмотреть сообщение
и сама память под my_struct_value_ никуда не делась, просто часть или все поля структуры занялись и я теперь не могу к ним обращается.
"занялась"? Чем "занялась"?
2
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
14.07.2023, 17:53  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
"занялась"? Чем "занялась"?
Занулилась хотел написать. В соответствии с вызванным (my_struct_value&& other).

Добавлено через 1 минуту
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Напишете копирование - будет копирование. Да, произошло копирование, потому что вы сами руками написали там копирование.
А что еще тогда можно написать ?
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
14.07.2023, 17:57
Optimus11, к теме , про RVO не слышал ?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,231
14.07.2023, 18:50
Цитата Сообщение от Optimus11 Посмотреть сообщение
А что еще тогда можно написать ?
Написать можно что угодно.

Можно было написать некое "перемещение". Но что такое "перемещение" для вашего класса зависит от задуманной вами семантики вашего класса. Я не знаю, что вы вам задумали за семантику вашего класса. Я не знаю, что значат хранящиеся в нём значения. Я не знаю, как он может/должен "перемещаться". Только вы это знаете.

Например, что это за указатели

C++
1
2
char* char_p;
wchar_t* wchar_t_p;
Они владеют той памятью, на которую указывают или нет? У вас в вопросе это оговорено? Нет, не оговорено. Так почему вы задаете участникам форума вопросы про "что еще тогда можно написать"? Откуда ж нам знать?

Если ни одно из полей вашего класса не имеет семантики владения каким-то ресурсом, то тогда ничего другого и нельзя написать. Для вашего класса семантика перемещения совпадает с семантикой копирования.

Добавлено через 50 минут
Цитата Сообщение от Optimus11 Посмотреть сообщение
Занулилась хотел написать. В соответствии с вызванным (my_struct_value&& other).
Зачем занулять? Основным назначением семантики перемещения является повышение эффективности кода, т.е. возможность делать перемещение в тех случаях, когда это допустимо и когда это более эффективно, чем копирование.

Вы же говорите о копировании, к которому сверху добавлено еще некое дополнительное действие - "зануление". Зачем? Лишнее действие понизит эффективность кода, а не повысит ее.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
14.07.2023, 19:07  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Зачем занулять? Основным назначением семантики перемещения является повышение эффективности кода, т.е. возможность делать перемещение в тех случаях, когда это допустимо и когда это более эффективно, чем копирование.

Вы же говорите о копировании, к которому сверху добавлено еще некое дополнительное действие - "зануление". Зачем? Лишнее действие понизит эффективность кода, а не повысит ее.
Да согласен. Понял.
Я правда так и не понял зачем придумали вводящее в заблуждение неокрепшие умы такие как мой - слово "перемещение".
По факту, опять такие если я правильно понял - всегда происходит копирование, да будет происходить, то, что я напишу в конструкторе "перемещения" - но по факту - это копирование.
Вопрос только в том, что копируется - только условная ссылка/указатель на ресурсы или копируется все.
То есть, опять такие, если я правильно понял, то std::move - это как бы просто удобная условно обертка над копирование указателей на выделенные ресурсы.

Ну или же я опять ничего не понял.
1
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
14.07.2023, 20:09
Optimus11, стратегии владения ресурсом и стратегии передачи владения, вот что здесь важно. Зачем концентрироваться на копировании? Это все равно что сказать "дом - это всего лишь забитые гвозди в правильные места", "но по факту дом - это забитые гвозди". Где-то да, но кому это интересно? Важно то, что получается в итоге. В смысле, гвозди не важны, важен дом в целом. Так и тут, копирование не важно, важно то, что вы получаете в итоге. А получаете вы возможность описывать порядок передачи владения ресурсом. Инструмент, с помощью которого вы получаете возможность использовать естественные ситуации, происходящие с вашими объектами (создание, передача, уничтожение) для управления владением. Понимаете?
3
фрилансер
 Аватар для Алексей1153
6461 / 5667 / 1130
Регистрация: 11.10.2019
Сообщений: 15,082
14.07.2023, 20:17
Лучший ответ Сообщение было отмечено Optimus11 как решение

Решение

Цитата Сообщение от Optimus11 Посмотреть сообщение
если я правильно понял - всегда происходит копирование
во всех случаях будет копирование, только реализованное по-разному:

1) "копирование" - создание в новом объекте места для данных, затем заполнение этого места копией данных из источника. Источник остаётся в прежнем состоянии.
2) "перемещение" - судьба источника никого не волнует. Разрешено отобрать все ресурсы у источника (например, скопировать только указатели на уже выделенную внутреннюю память). Но при этом нужно обеспечить адекватное, не поломанное, состояние источника - то есть, внутри источника эти указатели обнулить, например. Если после перемещения произойдёт работа с источником, ничего не должно сломаться, но при этом новое содержимое источника в общем случае неизвестно (точнее - поведение можно вычитать из документации)

1 и 2 - это общее, всеми ожидаемое поведение. Но всё же никто не запрещает реализовать эти два поведения иначе
2
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,231
14.07.2023, 20:50
Цитата Сообщение от Optimus11 Посмотреть сообщение
Я правда так и не понял зачем придумали вводящее в заблуждение неокрепшие умы такие как мой - слово "перемещение".
Потому что тех случаях, когда перемещение действительно что-то дает с точки зрения эффективности (то есть класс не является "плоским"), его семантика перемещения будет сильно отличаться от семантики копирования. Там действительно будет именно перемещение.

Цитата Сообщение от Optimus11 Посмотреть сообщение
но факту, опять такие если я правильно понял - всегда происходит копирование, да будет происходить, то, что я напишу в конструкторе "перемещения" - но .
Во-первых, не понимаю этой фразы. Возьмите к примеру std::string или std::vector. Для них семантика перемещения сильно отличается от семантики копирования. О каком "по факту это копирование" может идти речь?

Во-вторых, одним из жизнеспособных вариантов реализации семантики перемещения является swap полей класса. В этом случае "по факту" будет обмен, а не копирование. Можно, наверное, напридумывать еще вариантов.

Цитата Сообщение от Optimus11 Посмотреть сообщение
Вопрос только в том, что копируется - только условная ссылка/указатель на ресурсы или копируется все.
А, с этой точки зрения... Ну с этой точки зрения все программирование - это "копирование" данных с одного места на другое... Тогда все на свете можно считать "копированием"... Но никакой пользы в такой примитивизации я не вижу.

Цитата Сообщение от Optimus11 Посмотреть сообщение
То есть, опять такие, если я правильно понял, то std::move - это как бы просто удобная условно обертка над копирование указателей на выделенные ресурсы.
std::move - это лишь способ заставить компилятор выбрать и вызвать функцию с параметром типа &&-ссылка. А что произойдет дальше зависит только от того, что написано внутри этой функции.
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
14.07.2023, 21:35
Цитата Сообщение от Optimus11 Посмотреть сообщение
Да согласен. Понял.
Я правда так и не понял зачем придумали вводящее в заблуждение неокрепшие умы такие как мой - слово "перемещение".
По факту, опять такие если я правильно понял - всегда происходит копирование, да будет происходить, то, что я напишу в конструкторе "перемещения" - но по факту - это копирование.
Optimus11, терминология в C++ (и не только), это такая себе минология тер. При передаче по значению - значение копируется, а при перемещении, значение остаётся на месте. Копируется объект ссылающийся на это значение. В этом смысле если что и перемещается, так это например, значение указателя на значение ("перемещаемого" ресурса). Объект принявший новый адрес будет писать/читать (если кодом задано) и чистить в деструкторе по этому адресу. Вы обратили в ноль значение "ограбленного" указателя. Это возможно. Но тогда у принявшего объекта остаётся обязанность заделетить свой указатель перед принятием нового участка памяти. Иначе будет утечка. Поэтому, обычно такие указатели свопят. Новый объект доволен (он получил что хотел и без затрат времени на предочистку) и старому есть что почистить к тому времени когда он будет покидать область.
Optimus11, ваша трудность состоит именно в том, что вы
Цитата Сообщение от Optimus11 Посмотреть сообщение
Концепцию rvalue ссылок я так понять и не смог
Пока не разберёте, будете ломиться в стену рядом с дверью. Кратко говоря, перемещение придумано для объектов имеющих указательную семантику. Тут не важно перегружает ли класс операции для указателя. Важно что внутри у него есть указатель или иной дескриптор, который владеет ресурсом. И этот дескриптор можно переустановить на другой ресурс. Когда вы хотите получить значение объекта, который больше не нужен, можно определить операцию передачи владения получателю. Что касается std::vector то тут вам следует разобраться отдельно. И push_back/emplace_back тоже разберите. Эти вещи прямого отношения к семантике перемещения не имеют.
Тема перемещения не лёгкая тема. С наскоку не выйдет. Разберитесь с категориями выражений и ссылками. Пока там темно, перемещение не сдвинется с места.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
14.07.2023, 21:35
Помогаю со студенческими работами здесь

Std::move
Добрый вечер, #include &lt;iostream&gt; using namespace std; class A { private: int x = 10; public: A(int q){ x = q; }

std::move()
Есть ли разница между следующими вещами: A = std::move(B); // and std::copy(B.begin(), B.end(), A.begin()); B.clear();

Optional и std::move
добрый день. разбираясь в исходниках optional'а из gcc, я понял, что там нигде не делается инвалидным только что перемещенный объект. ...

Функция std::move()
struct DotPosition { long x; long y; }; std::vector&lt;DotPosition&gt; dots; DotPosition dot; dot.x = x; dot.y = y; ...

emplace и std::move
есть код для чтения кадров с камеры , нахождения лица и вывода этого всего на экран. #include &lt;opencv2/opencv.hpp&gt; #include...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru