Зачем нужны указатели в C++?

Поділитися
Вставка
  • Опубліковано 16 лис 2024

КОМЕНТАРІ • 71

  • @nikitos-mw9nb
    @nikitos-mw9nb 3 місяці тому +14

    Ты один из немногих людей которые могут понятно, кратко обьяснить материал. Большое тебе спасибо за работу!!!

  • @randomcreations1079
    @randomcreations1079 3 місяці тому +7

    Очень доступно объяснил сложную для многих тему. Спасибо

  • @stupnum8764
    @stupnum8764 4 місяці тому +21

    Дополню. Стек может быть каким угодно размером, все это настраивается, по умолчанию в динуксе 10мб, в винде 1мб. Еще важно, стек на самом деле принадлежит не процессу, а потоку, у каждого потока свой стек.

  • @qq-tn7bc
    @qq-tn7bc 3 місяці тому +5

    Спасибо большое, очень просто и понятно, идеально

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому +2

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

  • @mihail8159
    @mihail8159 4 місяці тому +5

    Спасибо , круто, по сути, коротко и ясно….

  • @megaspace-wy9mw
    @megaspace-wy9mw 5 місяців тому +9

    отлично рассказал, сохранил в плейлисте!

    • @Dima-Teplov
      @Dima-Teplov  5 місяців тому +3

      Спасибо!

    • @megaspace-wy9mw
      @megaspace-wy9mw 5 місяців тому +2

      @@Dima-Teplov быстро проверил другие видео и подписался

  • @ServusSovereign
    @ServusSovereign 3 місяці тому +2

    Красавчег! Спасибо!

  • @viper_0097
    @viper_0097 5 місяців тому +7

    еще одно применение указателей - очень легко выбирать одну переменную между несколькими. Например, вам нужно менять картинки в зависимости от каких-либо событий. присваивать значение слишком дорого, зато можно сделать указатель на картинку. И в коде просто менять адрес указателя на нужную картинку и от указателя отрисовывать её. Это намного лучше, чем если бы писать какие-нибудь свичи с перечислениями картинок.

    • @brinza888
      @brinza888 4 місяці тому

      в C++ для этого есть ссылки, а голые указатели использовать категорически не рекомендуется

    • @viper_0097
      @viper_0097 4 місяці тому +1

      @@brinza888 эм, нет. Ссылку нельзя поменять, в отличие от указателей.

    • @brinza888
      @brinza888 4 місяці тому

      @@viper_0097 это все верно, но в вашем случае вместо «голых» указателей все же лучше использовать shared_ptr или unique_ptr.

    • @viper_0097
      @viper_0097 4 місяці тому

      @@brinza888 Ну... так они же для работы с кучей нужны, я же вам говорю; они вызывают ошибку, если им дать адрес на переменную в стеке.
      Я говорю именно про выборку между адресами каких-то переменных, чтобы упрощать код. Я сам использую и умные указатели, и обычные: первые, чтобы хранить в них ресурсы, вторые, чтобы делать то, что я писал выше: указывать.

    • @8olegator8
      @8olegator8 4 місяці тому +1

      @@brinza888 а что это такое за боязнь голых указателей? Они и без одежды хороши, если уметь ими пользоваться и корректно освобождать)

  • @denis-dy4lo
    @denis-dy4lo Місяць тому +2

    В начале видео вы говорите: "когда вы обьявляете переменную, она автоматически размещается в стеке" и в конце видео, когда показываете примеры обьявляете те же переменные, но они вдруг размещаются в куче, несоответствие какое-то, и второй щепетильный момент- зачем нужен стек, если все данные можно сразу в кучу класть, да и почему нельзя в принципе увеличить размер стека до размеров кучи?

    • @Dima-Teplov
      @Dima-Teplov  29 днів тому +3

      Здравствуйте, Денис! Это хорошие вопросы, спасибо! В конце видео я говорю о том, что есть возможность создавать переменные не в стеке, а в куче, просто я не показываю как.
      Насчет размера стека. Память - это общий ресурс для всех программ, стек - это сегмент памяти, который строго резервируется за этой конкретной программой (пока она работает). Если бы стек был размером 1 ГБ, то каждая программа при запуске «съедала» бы 1 ГБ минимум. Поэтому стек не делают таким большим. Куча устроена иначе: в ней память можно выделить, когда она вам нужна, и можно освободить, если она больше не нужна.
      Стек вообще очень важный сегмент памяти, он используется для вызова функций, передачи аргументов в функции и много еще для чего, кроме хранения переменных. И выделение памяти в стеке работает гораздо быстрее, чем в куче.
      Теперь немного с юмором. Стек - это холодильник у вас дома, куча - это магазин. Создать переменную в стеке - это как открыть холодильник и взять оттуда мороженое. Выделить память в куче - это как сходить в магазин за мороженым. Теперь я задам вам ваши же вопросы, а вы попробуйте на них ответить.
      1. «Зачем нужен холодильник, если сразу можно сходить в магазин»?
      2. «Почему нельзя в принципе сразу увеличить размер холодильника до размера магазина?»

  • @tvsettv
    @tvsettv 3 місяці тому +1

    Указатели это как бы маркировка на ящике. Это Все что нужно знать об указателях. Маркировки могут быть разные, в зависимости, что лежит там.

  • @проха_картоха
    @проха_картоха 4 місяці тому +3

    Очень хорошо обьяснили❤

  • @kosiak10851
    @kosiak10851 3 місяці тому +1

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

  • @ted_res
    @ted_res 3 місяці тому +3

    Есть ещё одна важная особенность указателей. При передаче объекта в фукнцию в качестве параметра (допустим, по значению) он будет скопирован. То же самое касается возвращаемого значения: оно будет скопировано. Если вы работаете с объектом, размер которого 10КиБ, он постоянно будет копироваться в полном объёме, если его постоянно передавать между функциями, а это дополнительное время процессора. Если же передавать указатель на объект, сам объект остаётся там, где и был, а копируется только указатель на него.

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому +1

      Все верно! В плейлисте по указателям есть отдельный пример, который это демонстрирует. ua-cam.com/video/r4tIRmRWPB0/v-deo.html

    • @f.linezkij
      @f.linezkij 3 місяці тому

      Вы говорите про то, как передать аргумент не по значению, а по ссылке: call-by-value vs. call-by-reference.
      Многие языки программирования не поддерживают указатели, но всё же поддерживают call-by-reference, например в Java это деоается с помощью амперсанта при имени передаваемой переменной, да и в C++ тоже. То есть это не объясняет, для чего вообще нужны указатели, если передавать аргумент по ссылке можно прекрасно и без них.

    • @ted_res
      @ted_res 3 місяці тому +1

      @@f.linezkij удачи вам вернуть значение из функции по ссылке.
      Говоря, что многие языки не поддерживают указатели, вы о каких именно языках говорите? Например в Java каждая переменная на экземпляр класса - это указатель под капотом. Часто о таком механизме говорят pass-by-object-reference, это не имеет отношения к pass-by-reference.
      Пишу на Java больше 15 лет, но первый раз слышу, что можно передавать значения по ссылке. Вероятно, вы спутали с С#.

  • @LithiumDeuteride-6
    @LithiumDeuteride-6 3 місяці тому +1

    Ещё надо про умные указатели.

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому

      Так как я записывал это изначально для школьников, то умные указатели сюда не вошли. Это, все таки, более сложная тема.

  • @alexeybaranov8869
    @alexeybaranov8869 4 місяці тому +1

    Еще можно endian менять :) short s = 0x0102; char* p = (char*)&s; *p = *p ^ *(p + 1); *(p+1) = *p ^ *(p + 1); *p = *p ^ *(p + 1);

  • @rikmorti4072
    @rikmorti4072 4 місяці тому +1

    Чувак продолжай, отличная подача. Лайк, подписка

  • @postoronny
    @postoronny 2 місяці тому +1

    Что такое "библиотека"?
    DLL?

  • @mihail8159
    @mihail8159 4 місяці тому +1

    ❤❤❤❤❤

  • @ВладиславГришин-ш7ш
    @ВладиславГришин-ш7ш 4 місяці тому +2

    можно вообще заглянуть - как устроен процессор, регистры, команды асма
    иии чудесным образом вопроса зачем не будет

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

    Четко

  • @DeadnWoon
    @DeadnWoon 3 місяці тому +1

    Было бы очень неплохо, если бы кто-то (к примеру, Вы) сделали видео о том, как в теории можно было бы обойтись без указателей...

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому +1

      Боюсь, что тогда это будет видео не про С++. Конечно, в некоторых задачах можно "обойтись без указателей", например, вместо динамического выделения памяти под массив можно использовать готовый класс std::vector. Однако надо понимать, что внутри этого std::vector все равно используются указатели, он просто "прячет" их от программиста, но это не значит, что они не используются. Указатели связаны с архитектурой компьютера (это адреса данных в оперативной памяти), поэтому в итоге они всегда используются в любой программе. Их можно только "хорошенько спрятать", как, например, это делает Python. Поэтому, если вы не хотите работать с указателями, то просто используйте языки программирования, в которых они "спрятаны".
      Если вы хотите просто ездить на машине, то, наверное, знать внутреннее устройство машины не обязательно. Но если вы хотите быть профессиональным водителем, то полезно разобраться в том как эта машина устроена изнутри. С++ - это язык, которые требует не только навыков программирования, но и знания некоторых основ работы компьютера и операционных систем. Если, вдруг, вам это не нужно, то просто используйте другой язык программирования, например, Python.

    • @DeadnWoon
      @DeadnWoon 3 місяці тому +1

      Да, конечно, я имел в виду именно то, что язык мог бы быть достаточно низкоуровневым и при этом не использовать указатели как отдельное явление. Язык может, скажем, иметь некий спецификатор flexible, который подразумевает, что данная переменная может менять свой размер. Язык может иметь некий оператор вроде a?b, который выдаёт true, если по адресу a есть b незанятых последовательных байт. Размещать переменные по конкретному адресу можно с помощью некоего оператора at. При этом языку совсем необязательно иметь отдельное явление под названием указатель. По крайней мере, я так это вижу.

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому +1

      @@DeadnWoon Если переменная может менять свой размер, то под нее изначально надо выделять память самого большого размера, который она может занимать. То есть придется ввести какое-то ограничение по размеру, например, 1 Кб и тогда все переменные этого типа будут заниматься в памяти 1 Кб даже, если на самом деле там хранится 1 символ. Это уже выглядит не эффективно. Можно выделять память динамически по необходимости, но такое выделение памяти работает гораздо медленнее, чем выделение памяти в стеке, значит, это будет работать медленно. На мой взгляд эта одна из основных проблем такого подхода. Основной принцип языка С++ - это эффективность, поэтому такие варианты в нем не рассматриваются.
      Размещать переменные по какому-то конкретному адресу не достаточно, надо еще этот адрес где-то хранить и иметь возможность получать к нему доступ. Где он будет храниться? Кроме того, как в вашем языке можно описать такую структуру, как "связный список" без использования указателей?

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

      @@Dima-Teplov Да, конечно, я имел в виду, что flexible и a?b работают с кучей. По поводу связного списка - надо подумать...

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

      @@DeadnWoon /фейспалм/

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

    Сейчас вышли новые процессоры с увеличенным L 1, L2 , L 3 хешем. Означаетли это, что стек будет больше у таких процессоров? Не 1 мб?
    Или нужно, что-то добовлять в код, чтобы получить плюшки от этого хеша?

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому

      Привет! Нет, стек - это понятие уровня программы, а не процессора. Когда из исходного кода на языка С++ собирается исполняемая программа, то используемая ей память организуется специальным образом. Каким именно - зависит от используемой операционной системы. Размер стека по-умолчанию различается в разных операционных системах, кроме того, некоторые IDE позволяют изменить размер стека программы в настройках линковщика. Однако суть от этого не меняется, размер стека фиксирован и не может быть изменен во время работы программы и, значит, он может переполниться.

  • @postoronny
    @postoronny 2 місяці тому +1

    Три ореха - это куча? (ц)

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

    Почему int x; будет размещен в стеке? Если он определен внутри функции - то да, в стеке. А если нет?

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

      А если нет, тогда в сегменте данных.

    • @Happy-Gappy
      @Happy-Gappy Місяць тому

      Если это локальная переменна то на стеке, если глоабальная то в сегменте данных

  • @MSaidu-sj6vx
    @MSaidu-sj6vx 3 місяці тому +2

    Чтобы было понятно "твердолобым" показывайте на примере простенькой программы, можно еще дебаггером пройтись по адресам и носом ткнуть. Вот тогда "дойдет" точно. Указатели, структуры - сложная штука, с наскока не понимают многие ( еще и объяснить "зачем это надо", не каждый преподаватель доносит ).

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому

      Да, спасибо, все верно. Собственно я так и сделал в этом курсе: stepik.org/course/196036/promo
      Это просто один из видеоуроков оттуда.

  • @ILYA1991RUS_Socratus
    @ILYA1991RUS_Socratus 3 місяці тому +1

    Это адрес.

  • @Варис-д3ш
    @Варис-д3ш 3 місяці тому

    Почему я не начал изучение языков с С+ а послушав советы взялся за Питон? С+ лучше дает понимание как работает железо

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому

      Да, такие языки как С и C++ действительно заставляют разбираться во внутренних механизмах работы программ. Однако Питон проще освоить и, если вам надо быстро что-то написать для себя, то это отличный вариант. С++ в основном используется там, где требуется скорость и эффективное использование ресурсов.

  • @timbrazh8512
    @timbrazh8512 4 місяці тому

    Допустим. Но как программа "узнает" что одну переменную надо поместить в стек, а другую в кучу?

    • @Dima-Teplov
      @Dima-Teplov  4 місяці тому

      В языке С++ для того, чтобы программа создала переменную, объект или массив в куче программист должен сам ей об этом сказать. Для этого используются операторы new. Иначе все локальные переменные и массивы будут размещаться в стеке.

    • @adrew4
      @adrew4 4 місяці тому

      @@Dima-Teplov нет не все, только значимые типы будут размещены в стеке. Пишу на c# но и там и там string например - ссылочный тип. Есть еще некоторые примеры. Но на самом деле в ряде случаев оптимизации это не прибавит, должны выполнятся несколько условий чтобы ваш стек попал именно в кеш L3-L2, иначе особого смысла в этом мало с точки зрения оптимизации процессов.

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому

      @@adrew4 Здравствуйте! С++ это не С#, тут все немного по-другому... В С++ нет понятия "значимый тип". В С++ string - это не втроенный тип, а пользовательский класс (хоть и библиотечный). Сам объект типа string располагается в стеке, а вот содержимое строки действительно может размещаться в куче (для достаточно длинных строк), а может и в стеке (для коротких). Если вам интересно, то можете поэкспериментировать сами. Вот ссылочка на простой пример: onlinegdb.com/Sg32CX3W8

    • @adrew4
      @adrew4 3 місяці тому +1

      @@Dima-Teplov я не совсем понимаю как работает ваш скрипт по ссылке, но если данные строки фактически располагаются в куче, а на стеке находятся размер и указатель на эти данные, то в таком случае выражение о том что string будет находится на стеке не совсем справедливо. И если это работает так, значит это идентично языку C#, хоть и безусловно многие вещи отличаются, в том же интернировании. По логам судя по всему короткая строка находится где-то ближе к участку памяти на стеке. Насколько правдиво и правильно так оценивать фактическое быстродействие не возьмусь судить. В том смысле, не может ли среда вас обманывать говоря о том что переменная на стеке, а на самом деле там находится лишь указатель и это было сделано для оптимизации, чтобы среда думала что она работает с фактическими данными, например. Не знаю как практически это использовать, но такое предположение. Когда мы говорим о стеке и куче, это прежде всего об оптимизации, и если данные все равно находятся в куче, они уже ни при каких обстоятельствах не смогут попасть на кеш процессора, и тогда уже все равно в каком месте находится ссылка на эти данные. Чтобы взять их для работы придется потратить больше времени. Возможно я ошибаюсь, и если все именно так как вы описали, значит я не все процессы c++ понял. Просто это действительно любопытный вопрос.
      Меня просто смутила эта строчка из вики:
      "*Стек**: как и в C#, локальные переменные (включая объекты строк) могут храниться на стеке. Например, если вы создаете объект `std::string` в функции, он будет храниться на стеке. Однако сам объект `std::string` содержит только данные о строке (например, указатель на данные, длину и емкость). Фактические данные строки могут храниться в куче."
      В C# можно так же принудительно создать многие обьекты на стеке, но для этого необходимо обладать некоторыми фишками взаимодействия.

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому

      @@adrew4 Да, мне кажется, это вопрос терминологии. Когда я говорю о том, что объект или переменная класса находится в стеке, то я вовсе не имею ввиду, что все данные с которыми этот объект работает тоже находятся в стеке.
      Если в объекте есть указатели, то они могут указывать в любое место памяти - одни на стек, другие на кучу, третьи на статическую память или на сегменты кода. Поэтому в языке С++ нет никакого смысла говорить о том, что объект находится в куче, если часть данных с которыми он работает расположена в куче.
      В статье, то что касается С++ вроде все написано правильно. С# я не знаю, поэтому ничего не могу про него сказать.
      Насчет примера. Операция & (взятия адреса переменной) в С++ выполняется во время работы программы и возвращает реальный адрес объекта в оперативной памяти. Поэтому никакого обмана тут нет. По стандарту языка С++ все локальные переменные размещаются в стеке. При создании объекта пользовательского типа он может (в конструкторе) выделить память как в куче, так и в стеке. Что обычно и реализуется в классе std::string.
      Память под локальные переменные выделяется в стеке потому что это работает гораздо быстрее, чем выделение памяти в куче. Это оптимизация производительности.
      Насчет кэширования памяти, к сожалению, я не могу вам ответить. Логично, что стек будет кэшироваться "лучше", но, насколько я знаю, данные в "куче" тоже могут кэшироваться при частом доступе к ним. Думаю, что тут вы разбираетесь лучше меня.

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

    Если возникает такой вопрос,то вы начали изучать С++ сильно неправильно .

    • @Dima-Teplov
      @Dima-Teplov  3 місяці тому

      Согласен, но, тем не менее, вопрос возникает у многих.

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

      Если возникает такой вопрос, то программирование вообще изучать не нужно. Это не ваше.