Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/9: Рейтинг темы: голосов - 9, средняя оценка - 4.78
3 / 3 / 0
Регистрация: 28.11.2018
Сообщений: 242

Как передается значение в функцию и почему после перемещения знач. остается?

14.07.2019, 23:05. Показов 1830. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Для меня это очень странный вопрос, т.к. не сказал бы что я уже профи в С++(да куда там... ), но вроде и не совсем новичок. И настиг такой вопрос:
Вот глянул про новый(относительно) стандарт C++11 с rvalue, lvalue, про функцию std::move() также узнал.

Немного о том, как я понял: lvalue - то что имеет какое-то выделенное место в памяти(объявленная переменная, объявленный объект итд); rvalue - то, что живет "моментом"(наши "волшебные" цифры, н-р: int y = 2/*волшебное число*/, или такие же строки итд).

Вот немного разобравшись, что это всё означает, как работает, в том числе и функция std::move(),, глянул какие параметры она принимает(функция), а именно - (_Ty&& _Arg). И здесь произошла небольшая коллизия в моей голове. Сразу пример кода:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
void F(std::string &&s) {
    std::cout << s;
}
int main() {
    std::string s = "smth";
    F(std::move(s));           //std::move(_Ty&& _Arg)
    std::cout << s;
        return 0;
}
/*
OUTPUT:
smthsmth
*/
1) Вот std::move(_Ty&& _Arg) принимает в п-ры rvalue, на что указывает два &&, то есть мы же должны и передать rvalue(ну в принципе логично ), но по факту, в коде, который у меня работает(выше) мы передаем lvalue(моя строка s) - но почему так? Как оно вообще заработало? Он требует передать rvalue(_Ty&&_Arg) но мы передаем lvalue - и оно работает!? Как, почему?

2) И еще один вопрос: по идее, при перемещении(как написано в описании функции, в разных видео с ютюба, где люди объясняют работу std::move(), да и с названия понятно) мы должны что-то перемещать(не копировать). То есть, объект был(в моем случае строка "smth") по адресу 500(например), потом я его от туда взял, и переместил на адрес п-ра моей функции, например 1000(адрес). Значит на адресе 500 - ничего не должно быть, а на 1000 - должен быть мой объект. А оно почему то так не работает, т.к. после прохода функции строка остается - почему так?? Она же должная "улететь" в функцию, по идее.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
14.07.2019, 23:05
Ответы с готовыми решениями:

Почему в функцию передается другая переменная?
Есть программа по односвязным спискам, которые надо объединить в двухсвязные #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; ...

Почему не передается массив в качестве параметра в функцию?
Всем привет и с Новым годом !!! =) Пишу приложение на Zend. Есть класс: class Application_Model_Request{ protected...

Почему не передается значение input
Почему не передается значение инпута ? &lt;input type=&quot;text&quot; name&quot;two&quot; &gt;&lt;/input&gt; в ...

10
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
14.07.2019, 23:52
Лучший ответ Сообщение было отмечено MJ_PRUTYG как решение

Решение

Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
т.к. после прохода функции строка остается - почему так??
У вас не было перемещения в этом коде. Вы только обозначили, что при передаче параметра s нужно рассматривать как rvalue. Это и делает move, т.е. всего лишь меняет категорию выражения, сам по себе он ничего не перемещает (да и некуда, там же просто ссылка).
Фактическое перемещение выполнил бы конструктор перемещения или оператор перемещения, но у вас они в коде не задействованы.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
void F(std::string &&s) {
    std::string tmp(std::move(s));
    std::cout << tmp;
}
int main() {
    std::string s = "smth";
    F(std::move(s));           //std::move(_Ty&& _Arg)
    std::cout << s;
        return 0;
}


Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Вот std::move(_Ty&& _Arg) принимает в п-ры rvalue, на что указывает два &&
Если кратко, то нет: && в случае std::move на rvalue не указывает. Т.к. move - шаблонная функция, то что конкретно она будет принимать выводится из типа аргументов.
Читайте про свертку ссылок.

Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
в разных видео с ютюба
На ютубе вы получите полузнания, т.е. половину от тех знаний, что есть у авторов видео, а у них они соответственно точно такие же неполные. Читайте книги. С++ невозможно полноценно осилить без книг.
2
3 / 3 / 0
Регистрация: 28.11.2018
Сообщений: 242
15.07.2019, 08:55  [ТС]
DrOffset, спасибо большое за объяснение и за ссылку на статью. За конструктор перемещения не подумал - забыл - это похоже и есть ответ на один из моих вопросов.

Цитата Сообщение от DrOffset Посмотреть сообщение
На ютубе вы получите полузнания, т.е. половину от тех знаний, что есть у авторов видео, а у них они соответственно точно такие же неполные. Читайте книги. С++ невозможно полноценно осилить без книг.
Для меня огромная проблема большинства книг, это то, что нужно их читать от начала - т.к. всё завязано между собой, почти везде. То есть, перепрыгнув на главу с ООП, я зачастую не понимаю о чём говорит автор, т.к. до этого он что-то упомянул в предыдущей теме, а в той теме, еще раньше что-то сказал... И так по цепочке. Вы, кажется, мне как то советовали прочесть С.Липпмана Пятое издание, я начал читать и первые 100 страниц я знал, я знал просто всё, о чём говорится, а перепгнув на нужный раздел...В общем, описал выше.

А вот книгу Кормена про алгоритмы, которую вы мне посоветовали - просто божественная находка для меня! Темы между собой не переплетены, что-то конкретное нужно узнать - переходишь на конкретную страницу...идеально!

Вот была бы такая же книга, но по С++... Ехх... Может вы знаете какую-нибудь?

Добавлено через 5 часов 38 минут
DrOffset, воот, в 8 утра только закончил разбираться со всем этим(спасибо еще раз за ссылку, которую вы мне сбросили - от туда всё черпал). И остался главный и единственный(надеюсь) вопрос: по факту, 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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//~~~~~~~~~~std::remove_reference
template<typename T>
struct remove_ref{
    using type = T;
};
template<typename T>
struct remove_ref<T&> {
    using type = T;
};
template<typename T>
struct remove_ref<T&&> {
    using type = T;
};
 
//~~~~~~~~~~std::move
template<typename T>
typename remove_ref<T>::type&& mv(T && arg) {
    return (static_cast<typename remove_ref<T>::type&&>(arg));
}
 
//~~~~~~~~~~user's data type
class Car {
private:
public:
    int amow;
    Car() : amow(4) {};
    Car(int a) : amow(a) {}
    Car(const Car &c) {
        amow = mv(c.amow);
    }
    Car& operator=(const Car& c) {
        amow = mv(c.amow);
        return *this;
    }
    Car(const Car&& c) {
        std::cout << &c << "\n";
        amow = mv(c.amow);
    }
    ~Car() {}
};
 
//~~~~~~~~~~swap c++14
template<class T>
void swap(T& a, T& b)
{
    T tmp(mv(a));
/*после перемещения знач. "a" остаются(ну в принципе и логично, т.к. в функции mv(std::move) просто приведение типа)*/
    a = mv(b);
    b = mv(tmp);
}
 
int main() {
    Car a = 2;          //create an object
    Car b = 7;          //create an object
 
    swap(a, b);
    std::cout << a.amow << " " << b.amow << "\n";
        return 0;
}
во всех случая работы в ф. swap() срабатывает 3 раза mv и три раза конструктор перемещения - но почему это быстрее...? не понимаю. Ведь значения после mv(T &&arg) остаются и в аргументе функции, и возвращает она просто rvalue - но быстрее, почему?!
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
15.07.2019, 10:26
MJ_PRUTYG, как уже сказали std::move на самом деле ничего не перемещает, а лишь делает каст к r-value, о нем лучше думать как о rvalue_cast() ф-и.
Почему перемещение быстрее копирования?
Все просто, потому что rvalue это по сути временный объект, который через секунду умрет, а значит мы можем "своровать" его данные, терять ему уже и так нечего, но это не сработает с фундаментальными и/или простыми (pod) классами, тк они фундаментальные, операции над ними может легко проводить сам процессор и оптимизировать компилятор, а pod'ы спокойно зачастую можно целиком загнать в регистр, поэтому здесь выиграша от перемещения в сравнении с копированием не будет.
Что касаемо «сложных» классов, например std::string, то здесь перемещение имеет смысл и роль перемещения выполняет соответствующий конструктор. И быстрее это будет как минимум из-за того, что не надо делать дополнительных выделений в куче как в случае с копированием, а можно просто украсть указатель))

Добавлено через 8 минут
Вернее, не то, что выиграша в перемещении фундаментальных типов не будет, а вообще, в целом, перемещение для фундаментальных типов не работает, там попросту нечего воровать, поэтому в int и остаются данные.

Добавлено через 11 минут
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
const Car&& c
Почему вы сделали c константным временным объектом?
Как вы тогда будете пытатся переместить (своровать) данные, даже если он умрет на следующей инструкции?
Вы же понимаете, что такой объект может быть помещен в ro-data сегменте, а const_cast к таким данным приведет к UB.
1
3 / 3 / 0
Регистрация: 28.11.2018
Сообщений: 242
15.07.2019, 10:31  [ТС]
Спасибо за ответ, но...
Цитата Сообщение от Azazel-San Посмотреть сообщение
не надо делать дополнительных выделений в куче как в случае с копированием, а можно просто украсть указатель
Этот момент не особо понял. То есть, если этот объект "секундный" то он с функции move() вернулся, а потом тут же улетел в конструктор... То есть он даже не создавался, а просто "перебрался" в другое место. Я всё верно понял?
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
15.07.2019, 10:40
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
То есть он даже не создавался
Всмысле не создавалася? Создавался конечно, откуда же нам тогда данные воровать?
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
а просто "перебрался" в другое место
Ну, да.
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Я всё верно понял?
Возможно..
C++
1
2
3
4
5
6
7
// есть некий класс dummy и у него есть поле в виде указателя на некие данные
// , а это его констркутор перемещения
dummy(dummy&& other) {
    this->ptr = other.ptr; // ptr - тот самый указатель и что мы здесь делаем? 
                           // Просто его воруем, other'у свои данные уже не нужны.
    other.ptr = nullptr;   // Обнуляем.
}
1
3 / 3 / 0
Регистрация: 28.11.2018
Сообщений: 242
15.07.2019, 10:59  [ТС]
Azazel-San, всё понял
Только маленькое уточнение: а требуется обнулять то, что мы "воруем"?
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
15.07.2019, 11:19
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
а требуется обнулять то, что мы "воруем"?
В общем случае - да. Как уже было сказанно, само перемещение ничего такого не делает и ничего не обнуляет. А перемещение, вернее, после перемещения объект становится не валидным.
0
 Аватар для Termit779
79 / 60 / 19
Регистрация: 22.11.2015
Сообщений: 193
15.07.2019, 11:47
Цитата Сообщение от Azazel-San Посмотреть сообщение
ничего не перемещает, а лишь делает каст к r-value,
Ничего не делает? О боже спасите мои яйки

Добавлено через 5 минут
Офсет старый сишник, он объяснит, что любое попалзновение имеет эффект. Проц все равно полезит на контроллер, и это вызовет побочный эффект

Добавлено через 2 минуты
Цитата Сообщение от Azazel-San Посмотреть сообщение
не валидным.
__________________
Прлтухшим
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.07.2019, 21:09
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Для меня огромная проблема большинства книг, это то, что нужно их читать от начала - т.к. всё завязано между собой, почти везде. То есть, перепрыгнув на главу с ООП, я зачастую не понимаю о чём говорит автор, т.к. до этого он что-то упомянул в предыдущей теме, а в той теме, еще раньше что-то сказал... И так по цепочке. Вы, кажется, мне как то советовали прочесть С.Липпмана Пятое издание, я начал читать и первые 100 страниц я знал, я знал просто всё, о чём говорится, а перепгнув на нужный раздел...В общем, описал выше.
Я все это слышал здесь много раз от разных людей Факт остается фактом, что бы вы не говорили. Ваши знания, а значит и доход, будут сильно страдать, если вы будете опираться только на видео или статьи. Вы либо дойдете до этих знаний сами, но спустя гигантское время, либо таки научитесь воспринимать информацию из книг. Я вообще не завидую тем, кто берется работать на С++ с такими половинными знаниями, они просто мучиться будут: бороться с языком, вместо того, чтобы решать задачи.

Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Вот была бы такая же книга, но по С++... Ехх... Может вы знаете какую-нибудь?
Ну вот книга Мэйерса по С++11 вполне читается не подряд. Там как раз дано одно из лучших изложений темы вашего вопроса.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
15.07.2019, 23:07
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Только маленькое уточнение: а требуется обнулять то, что мы "воруем"?
Посудите сами. Если после перемещения объект остался в валидном для дальнейшего использования состоянии, то ничего обнулять не нужно. Если же объект стал непригоден для дальнейшего использования, то ничего законно "обнулить" Вы не сможете.

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

Что касается классов стандартной библиотеки, то объекты после перемещения остаются в валидном, но неспецифицированном состоянии (valid but unspecified state).
valid but unspecified state
an object state that is not specified except that the object’s invariants are met and operations on the object behave as specified for its type
[ Example: If an object x of type std::vector<int> is in a valid but unspecified state, x.empty() can be called unconditionally, and x.front() can be called only if x.empty() returns false. —end example]
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.07.2019, 23:07
Помогаю со студенческими работами здесь

Почему внутри sub не передается значение?
Поскажите плиз, вот подпрограмма для Access Private Sub NewData_Click() strFirmName$ = DoCmd.Close DoCmd.OpenForm 'NewClients' ...

Почему значение не передается в уравнение?
Почему значение &quot;р&quot; не передается как индекс массива в уравнение? #include &lt;math.h&gt; #include &lt;stdio.h&gt; #include &lt;conio.h&gt;...

В функцию передается пустое значение
Здравствуйте. Есть функция, для вывода информация, используется еще одна функция. Вот код: function print_result($result_name,...

Почему не передается последнее значение из datagridview в массив?
Добрый вечер. Подскажите пожалуйста почему не передается последнее значение из datagridview В массив? dgw = new string; for...

Скажите, пожалуйста, почему в переменной fn остаётся значение 1, а не символ, введенный с клавиатуры?
Добрый день! Вспоминаю программирование. Скажите, пожалуйста, почему в переменной fn остаётся значение 1, а не символ, введенный с...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере 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 На первой гифке отладочные линии отключены, а на второй включены:. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru