Введение в ИТ. Rvalue-ссылки и семантика перемещения

Поділитися
Вставка
  • Опубліковано 4 чер 2020
  • Левосторонние (lvalue) и правосторонние (rvalue) значения. Проблемы применения традиционных конструкторов копирования и операторов присваивания. Решение в стандарте C++11. Правосторонние ссылки. Перемещающие конструкторы копирования и перемещающие операторы присваивания.
    Скринкаст семинара Павла Викторовича Буркова.

КОМЕНТАРІ • 30

  • @Dima-uz8gi
    @Dima-uz8gi 12 днів тому

    О! Очень хорошо объясняете, четко понятно, отличная дикция, спасибо!

  • @balenciagastore
    @balenciagastore Рік тому +9

    этот комент я пишу в 2023 году 19.03 и этот ролик по r-value самый офигенный и понятный . Автор спасибо тебе из 2023 💜

  • @user-yw9bq1pt9v
    @user-yw9bq1pt9v 4 місяці тому +4

    Самое адекватное объяснение этой темы. А то читал литературу и там так все запутанно объясняют)Спасибо !!!!!

  • @hovhannesmovsisyan8326
    @hovhannesmovsisyan8326 2 роки тому +1

    Супер

  • @nikitun85
    @nikitun85 Рік тому +1

    Елы-палы, чел, помогай тебе всевышний! Я, видимо, не с того начал (Майерс, страусиный труп). После первых прочтений было понятно чуть больше, чем нихера. А тут как по маслу. Очень хорошо объяснил. Спасибо!

  • @Kyberbote
    @Kyberbote 2 роки тому +1

    На 11:00 разве не конструктор копирования вызывается? У нас же на момент возврата из функции объект Array a еще не проинициализирован, поэтому мы его создаем из объекта temp, возвращенного функцией, для чего вызываем конструктор копирования.
    Оператор присваивания вызовется в следующем случае:
    Array a(1);
    a = createBigArray(10);

  • @user-qp3lt4ps8c
    @user-qp3lt4ps8c 11 місяців тому

    Хорошее объяснение, спасибо!

  • @user-ku4nn5pw8p
    @user-ku4nn5pw8p Рік тому

    Спасибо за хорошее обьяснение)

  • @djves6934
    @djves6934 6 місяців тому

    Отличное объяснение. Спасибо

  • @user-rf8tj6hi8s
    @user-rf8tj6hi8s 3 роки тому +2

    Спасибо, понял.

  • @dzm_mlc
    @dzm_mlc 8 місяців тому

    В видео очень не хватает примеров как эту же задачу можно решить другими способами, например передачей new Array из createBigArray() через указатель, а то создаётся впечатление что проблему кроме как move семантикой ни как не решить. Ну и сравнительный анализ хоть небольшой: чем удобнее, когда использовать какой способ

    • @dzm_mlc
      @dzm_mlc 8 місяців тому

      К примеру в embedded программировании бывает нужно избегать аллокации памяти, и move-семантика может в этом помочь. Хотя даже в этом случае есть другие методы, например, использовать наследование. Либо в рамках задачи можно создать Array и передать его на заполнение в fillRandomData()

  • @UmbertoFellinni
    @UmbertoFellinni Місяць тому

    Чето тут не то, тут есть косяк - перемещающий функционал не вызывается при создании объекта таким способом: Array a = Create(1000); Оператор = перемещения вызывается в этом случае: Array a(10); a = Create(10000); В общем, чето тут как то не то.

  • @sleepyNovember_project
    @sleepyNovember_project 3 місяці тому

    Как будто настоящего профессора слушаешь, да ещё всё так хорошо объясняется

    • @UmbertoFellinni
      @UmbertoFellinni Місяць тому

      Если не считать, что то, что он понаписал - на самом деле не работает так, как он рассказывает. Пошаговая отладка четко это показывает. Автор тут накосяпорил конкретно так.

  • @normannspectator
    @normannspectator 11 місяців тому +1

    Тема rvalue-ссылок не раскрыта.

    • @UmbertoFellinni
      @UmbertoFellinni Місяць тому

      Более того, написанный код - ошибочный, я проверил самолично, он не работает так, как рассказывает автор.

  • @UmbertoFellinni
    @UmbertoFellinni Місяць тому

    Не, реально, какая то фигня получается. Чувак, вот ты сам проверь в пошаговой отладке то, чего понаписал то. Ну не работает твоя писанина так, как ты рассказываешь. Я лично проверил в разных компиляторах во всевозможных вариантах - не так это работает. Кароч, чувак, ты чето здорово накосяпорил. И если ты - препод в Бауманке, то "это фиаско, братан"(С). Реально, чувак, тут какая-то ошибка. Если в Бауманке преподы не разбираются в предмете, то о каком "прорыве" в шаРашке нам твердят по телику? Это ваще полный ахтунг чето.

  • @Poker-s_S.V.
    @Poker-s_S.V. 4 роки тому

    "Ни че не понял, но очень интересно"...))) А, кто мешает передавать по указателю???????????????................... Да и ссылка это всего лишь символьный псевдоним адреса для компилятора. Все переменные по логике происходящего это ссылки. В принципе, отличия ссылки от указателя в том, что ссылка всегда имеет один и тот же адрес, а указатель может иметь любой адрес, но все они типизированные псевдонимы, с отсчетом ячейки по размеру типа, и понимаются только компилятором. Короче пока программа в текстовом редакторе, то у тебя есть и R и L, а после компиляции они все просто по адресу в ячейке...))

    • @user-no5de3ge1x
      @user-no5de3ge1x  4 роки тому +3

      Попробуйте получить указатель на результат вычисления выражение вида например (a+b). Вы совершенно правы, когда пишете, что после компиляции данные всегда окажутся в ячейке с некоторым адресом. Но до компиляции можно получить указатель или классическую Lvalue-ссылку на именованную переменную, а не на результат вычисления выражения. Появление Rvalue-ссылок как раз призвано решить эту проблему. И вслед за этим появляются качественно новые решения, основанные на семантике переноса (перемещения) - особые типы конструкторов копирования и операторов присваивания. Их применение позволяет избежать избыточных операций копирования данных из одних буферов в другие. А обычные Lvalue-ссылки действительно являются лишь "синтаксическим сахаром", обёртками над указателями.

    • @Poker-s_S.V.
      @Poker-s_S.V. 4 роки тому

      ​@@user-no5de3ge1x РАЗВЕРНИ СООБЩЕНИЕ, в самом конце ответ на &(a+b) = new int(a + b);
      Не, ну это и понятно, значения а и b, лежат в двух разных ячейках, у которых разные адреса, по этому
      такое не прокатит:
      int* foonc(int a, int b)
      {
      return &(a+b);
      }
      А, такое прокатывает:
      int* foonc(int a, int b)
      {
      return &(a);
      }
      Хотя я думаю, что СКОБКИ ( ... ) должны быть определяющими ячейку результата, ведь просто результат (a+b) я могу вернуть, следовательно, казалось бы указатель на результат тоже должно быть возможным вернуть.
      Результат вернуть можно:
      int fooncI(int a, int b)
      {
      return (b + a);
      }
      Все потому, что ячейка результата временная, даже если я верну указатель ячейки созданной в функции, она все равно временная, и там может оказаться все что угодно, следовательно, результат нужно фиксировать к примеру в глобальном указателе, это логично.
      Для того чтоб зафиксировать память существует оператор выделения памяти NEW, по этому при возврате указателя достаточно добавить этот оператор и тип возвращаемого отсчета памяти:
      int* fooncP(int a, int b)
      {
      return new int(a + b);
      }
      А, если ты еще и присвоишь ссылочный псевдоним, то и освобождать память не нужно будет, я так думаю, так как все переменные являются ссылками:
      Использование:
      int* pc = fooncP(5, 6); //вызываю функцию и получаю указатель на память.
      int& cc = *pc; //присваиваю памяти псевдоним.
      std::cout

    • @Poker-s_S.V.
      @Poker-s_S.V. 4 роки тому

      @@user-no5de3ge1x А вот вкратце указатель на (a+b):
      int* fooncP(int a, int b)
      {
      return new int(a + b); //чтоб вернуть указатель на результат, нужно ячейку зафиксировать
      //оператором выделения памяти NEW, иначе, так как функция временный объект то и возвращаемое
      //значение функцией находится во временной памяти, которая освободится после использования
      //функции, и тем самым по адресу в ячейке может оказаться все что угодно.
      }

    • @MariaEsenina
      @MariaEsenina 3 роки тому +3

      @@user-no5de3ge1x в чистом C без труда работают через указатели, правда там несколько иной стиль кода. В C возвращаемое значение функции - это часто не нужное нам значение, а код ошибки (0 если всё норм), а результат выполнения функции - это дополнительный указатель в качестве входного параметра, говоря проще
      int foo(int* input, int* output) {/*code*/}; //output - это то это результат выполнения, который нам интересен, а return - это результат успешности выполнения функции (если функция однозначна можно было бы использовать void, но по привычке все используют int).
      То что в итоге нагородили в C++ - это безумие, которое не только интуитивно не понимают даже "как бы" продвинутые разработчики, но и легко создать трудноуловимые ошибки, при этом ещё и количество строк кода резко увеличивается решая исключительно формальную обслуживающую задачу, а единственный профит от этого - это то, что класс потом можно будет использовать эффективно, однако если потребуется что-то поменять то в C-стиле можно переписать несколько строк и всё без труда заработает, а в C++ rvalue-ссылками придётся следить чтобы нигде ничего не сломать. +Ещё выбрали обозначение идиотское (&&) и тоже не интуитивное (по логике это как взятие адреса у адреса), обычные ссылки имеют логическую подоплёку, т.к. & символизирует "адресность", что символизирует в этом контексте && - чёрт его знает, просто "потому что потому". В результате получается так, что даже в C++ чаще можно встретить работу без копирования на обычных указателях в стиле C вместо танцев на граблях с move-семантикой в стиле Rust. Кстати почти никто из "знатоков" move семантики не рассказывает что именно происходит с памятью, большинство я уверена даже сами не знают :), и вообще move-семантику если и изучать/преподавать, то лучше отвлечься от кода и нарисовать области памяти и на таком примере пояснить что именно мы делаем, так заодно сразу же всплывёт разница между lvalue и rvalue ссылками, а видео, в целом, неплохое, лучше чем у многих.

    • @user-mw2cd3lu8n
      @user-mw2cd3lu8n Рік тому +5

      Ввели rvalue только с одной целью - продать больше книжек по C++ новой редакции. Просто бизнес. 🤣

  • @username8614
    @username8614 Рік тому +1

    такое ощущение, что этот маленький ребёнок в универе преподом работает. это не лечится

  • @UmbertoFellinni
    @UmbertoFellinni Місяць тому

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

  • @UmbertoFellinni
    @UmbertoFellinni Місяць тому

    Кароч, детально разобравшись в вопросе, подытожу - автор видоса допустил принципиальную ошибку в использовании перемещающего оператора и вообще в понимании всего процесса работы. Перемещающий оператор присваивания не будет вызываться при создании нового объекта класса Array a = Create(); Он будет вызываться только для УЖЕ СОЗДАННОГО объекта. Ну и в показанном примере все что написано, в принципе не нужно, работает и без него без каких-либо проблем. Прискорбно, что сей горе-препод из Бауманки пытается учить других, при этом сам не понимает, как тут реально работает. Ему всего лишь нужно было запустить пошаговую отладку и проследить за исполнением кода. Он наверно потому и не стал запускать отладку, что она покажет совсем не то, про что рассказывает препод. Печально конечно. Сей бодячий фейл показывает истинное состояние дел в нашерашке в сфере ИТ, в противовес тому, что сыплется на нас с зомбоящика.

  • @phat80
    @phat80 9 місяців тому

    вы не умеете объяснять, преподавание - не ваше

    • @sashatim8244
      @sashatim8244 5 місяців тому +2

      C++ не ваше, учите питон дядька

    • @phat80
      @phat80 5 місяців тому

      @@sashatim8244 тогда сразу же нашел отличное объяснение, но естественно, как всегда, в англоязычном сегменте. А что мне учить без вас разберусь. А проблема отечественных «учителей» она тянется еще с незапамятных времен. Любые книги, учебники, видеоуроки убоги за очень редким исключением. Это касается не только ЯП, а вообще всего.