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

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

14.07.2019, 23:05. Показов 1812. Ответов 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
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
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
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
15.07.2019, 21:09
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Для меня огромная проблема большинства книг, это то, что нужно их читать от начала - т.к. всё завязано между собой, почти везде. То есть, перепрыгнув на главу с ООП, я зачастую не понимаю о чём говорит автор, т.к. до этого он что-то упомянул в предыдущей теме, а в той теме, еще раньше что-то сказал... И так по цепочке. Вы, кажется, мне как то советовали прочесть С.Липпмана Пятое издание, я начал читать и первые 100 страниц я знал, я знал просто всё, о чём говорится, а перепгнув на нужный раздел...В общем, описал выше.
Я все это слышал здесь много раз от разных людей Факт остается фактом, что бы вы не говорили. Ваши знания, а значит и доход, будут сильно страдать, если вы будете опираться только на видео или статьи. Вы либо дойдете до этих знаний сами, но спустя гигантское время, либо таки научитесь воспринимать информацию из книг. Я вообще не завидую тем, кто берется работать на С++ с такими половинными знаниями, они просто мучиться будут: бороться с языком, вместо того, чтобы решать задачи.

Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Вот была бы такая же книга, но по С++... Ехх... Может вы знаете какую-нибудь?
Ну вот книга Мэйерса по С++11 вполне читается не подряд. Там как раз дано одно из лучших изложений темы вашего вопроса.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 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
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru