В C++ я не могу понять указатели и классы

Я только что закончил колледж и уже некоторое время работаю на C++. Я понимаю все основы C++ и использую их, но мне трудно понять более сложные темы, такие как указатели и классы. Я прочитал несколько книг и руководств, и я понимаю примеры в них, но затем, когда я смотрю на некоторые сложные примеры из реальной жизни, я не могу их понять. Это убивает меня, потому что я чувствую, что это мешает мне вывести программирование на C++ на новый уровень. У кого-нибудь еще была эта проблема? Если да, то как вы его преодолели? Кто-нибудь знает какие-нибудь книги или учебники, которые действительно хорошо описывают указатели и концепции классов? или, может быть, какой-нибудь пример кода с хорошими описательными комментариями с использованием расширенных указателей и методов классов? любая помощь будет принята с благодарностью.

Из любопытства, какие языки вы изучали в колледже? Кроме чисто функциональных языков, я не могу придумать никаких языков, в которых нет ни указателей, ни классов.

David Locke 19.09.2008 00:10

К вашему сведению, указатели и классы - это основы C++.

Wedge 19.09.2008 00:18

P.S. C++ - очень богатый и широкий язык. Если вы не можете понять сложные примеры, это не обязательно означает, что вам чего-то не хватает («продвинутая» кроличья нора C++ уходит очень и очень глубоко). Было бы полезно, если бы вы предоставили более конкретную информацию.

Wedge 19.09.2008 00:22

Как именно вы какое-то время работаете с C++ без этих знаний ...? C++ без классов звучит как C, а C без указателей звучит как um .....

Aardvark 19.09.2008 00:25

Позвольте предположить - вы пишете код для вычислительной математики, и ваше непонимание указателей мешает обработке многомерных данных. Закрывать?

user3458 19.09.2008 01:07

Вы не разбираетесь в C++, если не понимаете концепцию классов. А если вы не понимаете указатели, то вы, вероятно, тоже не знаете C ... Система образования не работает

FlySwat 19.09.2008 02:28

Я попытался прояснить это в своем вопросе, но, возможно, я этого не сделал, что я понимаю указатели и классы с точки зрения уроков и примеров из учебников. Но когда мне нужно прочитать и понять чужой код, например программный API, с указателями и классами, у меня возникают проблемы с пониманием.

timmyg 19.09.2008 07:28

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

timmyg 19.09.2008 07:36
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
8
6 631
27

Ответы 27

Представьте, что указатель - это адрес массива.

x = 500; // memory address for hello;
MEMORY[x] = "hello"; 
print  MEMORY[x]; 

это графическое упрощение, но по большей части, если вы никогда не хотите знать, что это за число, или устанавливать его вручную, все должно быть в порядке.

Когда я понял C, у меня было несколько макросов, которые более или менее позволяли использовать указатели так же, как мы - индекс массива в памяти. Но я давно потерял этот код и давно забыл.

Я помню, это началось с

#define MEMORY 0; 
#define MEMORYADDRESS( a ) *a;

и это само по себе вряд ли полезно. Надеюсь, кто-нибудь еще сможет расширить эту логику.

Я считаю, что это очень полезное упражнение. Черт возьми, во многих встроенных системах у меня не было указателя на вещи, выделенные для меня, у меня был индекс массива :).

Doug T. 19.09.2008 00:07

для тех из вас, кто ругает меня за этот пост, это работает. Я пользовался им, помогал другим. Тот факт, что ОС все это абстрагирует для вас, не имеет значения для упражнения.

Kent Fredric 19.09.2008 00:10

Да, я этого не понимаю, я думаю, что это отличный способ понять указатели. Массивы легче понять, чем указатели, ИМО, поэтому я думаю, что это отличная отправная точка.

Doug T. 19.09.2008 00:17

Для указателей:

Я обнаружил, что эта почта провел очень вдумчивое обсуждение указателей. Может, это поможет. Вы знакомы с такими ссылками, как C#? Это то, что на самом деле относится к чему-то другому? Вероятно, это хорошее начало для понимания указателей.

Также посмотрите пост Кента Фредрика ниже о другом способе познакомиться с указателями.

Раньше у меня была проблема с пониманием указателей на паскале :) Как только я начал делать указатели на ассемблере, действительно был единственным способом доступа к памяти, и это меня просто поразило. Это может показаться маловероятным, но попытка ассемблера (что всегда полезно, чтобы попытаться понять, что такое компьютеры на самом деле), вероятно, научит вас указателям. Классы - ну, я не понимаю вашу проблему - вы учились чисто структурированному программированию? Класс - это просто логический способ взглянуть на модели реальной жизни - вы пытаетесь решить проблему, которая может быть выражена в нескольких объектах / классах.

Чтобы понять указатели, я не могу рекомендовать книгу K&R достаточно высоко.

Лучшая книга, которую я прочитал по этим темам, - «Мыслить на C++» Брюса Экеля. Вы можете скачать его бесплатно здесь.

Указатели и классы - это совершенно разные темы, поэтому я бы не стал их так объединять в одну кучу. Из двух я бы сказал, что указатели более фундаментальны.

Вот хорошее упражнение для изучения того, что такое указатели:

  1. создать связанный список
  2. повторить его от начала до конца
  3. переверните его так, чтобы голова теперь была спиной, а спина теперь головой

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

Эта ссылка имеет видео, описывающее, как работают указатели с пластилином. Информативно и легко усваивается.

Эта страница имеет хорошую информацию об основных классах.

Все, что связано с пластилином, получает +1 в моей книге.

Aardvark 19.09.2008 00:24

Указатели и классы - не слишком сложные темы в C++. Они довольно фундаментальны.

Для меня указатели укрепились, когда я начал рисовать прямоугольники со стрелками. Нарисуйте рамку для int. А int * теперь представляет собой отдельное поле со стрелкой, указывающей на поле int.

Так:

int foo = 3;           // integer
int* bar = &foo;       // assigns the address of foo to my pointer bar

С помощью поля (панели) указателя у меня есть выбор: смотреть на адрес внутри поля. (Это адрес памяти foo). Или я могу манипулировать тем, к чему у меня есть адрес. Эта манипуляция означает, что я перехожу по этой стрелке к целому числу (foo).

*bar = 5;  // asterix means "dereference" (follow the arrow), foo is now 5
bar = 0;   // I just changed the address that bar points to

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

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

timmyg 19.09.2008 00:27

Я поддерживаю это. Для новичков всегда ВСЕГДА переводите «указатель» в «адрес» и «разыменование» в «путешествие по адресу», как при вождении автомобиля. указатели на указатели становятся почтовыми ящиками пересылки - адресами, которые, когда вы идете туда, вы находите другой адрес вместо места хранения.

Aaron 19.09.2008 03:02

Вполне возможно, что большая часть этого кода написана не слишком хорошо. Однажды я потратил много времени, пытаясь понять, как работает код с большим количеством указателей. Я сдался и спросил начальника. Он посмотрел на него 2 секунды и сказал: «Ага. Это вызовет сбой. Лучше почините». Опыт: способность смотреть на образец, видеть, как он делает что-то странное, и думать: «С этим что-то не так», а не «Со мной что-то не так».

deworde 08.06.2009 20:07

Для занятий:

Момент прорыва для меня наступил, когда я узнал об интерфейсах. Идея абстрагироваться от деталей того, как вы пишете, решала проблему и предоставляла только список методов, которые взаимодействуют с классом, была очень проницательной.

Фактически, мой профессор прямо сказал нам, что он будет оценивать наши программы, подключая наши классы к своей тестовой оснастке. Оценка будет производиться на основе требований, которые он нам поставил, и того, вылетела ли программа.

Короче говоря, классы позволяют обернуть функциональность и называть ее более понятным образом (в большинстве случаев всегда есть исключения)

Обвязка тестирования - это код, который выполняет другой набор кода. У моего профессора была основная программа, которая вызывала функции в нашем классе. Он запускал тест, ставил оценку, удалял ваш файл, вставлял следующий файл ученика в свое решение и повторял весь процесс.

Jason Z 19.09.2008 14:30

Книга, которая взломала для меня указатели, была Иллюстрация Ansi C Дональда Алкока. Он полон нарисованных от руки прямоугольников и диаграмм со стрелками, которые иллюстрируют указатели, арифметику указателей, массивы, строковые функции и т. д.

Очевидно, это книга на тройку, но по основным основам ее сложно превзойти

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

Просмотр объектно-ориентированных парадигм, таких как наследование, в графической форме - очень мощный способ понять эту концепцию.

UML дистиллированный Мартина Фаулера - хорошее краткое введение.

Из ответа lassevek на аналогичный вопрос по SO:

Pointers is a concept that for many can be confusing at first, in particular when it comes to copying pointer values around and still referencing the same memory block.

I've found that the best analogy is to consider the pointer as a piece of paper with a house address on it, and the memory block it references as the actual house. All sorts of operations can thus be easily explained:

  • Copy pointer value, just write the address on a new piece of paper
  • Linked lists, piece of paper at the house with the address of the next house on it
  • Freeing the memory, demolish the house and erase the address
  • Memory leak, you lose the piece of paper and cannot find the house
  • Freeing the memory but keeping a (now invalid) reference, demolish the house, erase one of the pieces of paper but have another piece of paper with the old address on it, when you go to the address, you won't find a house, but you might find something that resembles the ruins of one
  • Buffer overrun, you move more stuff into the house than you can possibly fit, spilling into the neighbours house

Я думаю, чтобы лучше понять указатели, было бы полезно посмотреть, как язык ассемблера работает с указателями. Концепция указателей действительно является одной из фундаментальных частей ассемблера и архитектуры инструкций процессора x86. Может быть, это позволит вам почувствовать, что указатели являются естественной частью программы.

Что касается классов, то, помимо парадигмы объектно-ориентированного программирования, я думаю, что может быть интересно взглянуть на классы с точки зрения низкоуровневого двоичного кода. Они не такие уж сложные в этом отношении на базовом уровне.

Вы можете прочитать Внутри объектной модели C++, если хотите лучше понять, что находится под объектной моделью C++.

Указатели, похоже, уже рассматриваются (без каламбура) в других ответах.

Классы являются фундаментальными для объектно-ориентированного проектирования. У меня были огромные проблемы с тем, чтобы ломать голову над ОО - вроде, десять лет неудачных попыток. В конце концов мне помогла книга Крейга Лармана «Применение UML и шаблонов». Я знаю, это звучит так, как будто это о чем-то другом, но на самом деле он отлично помогает вам погрузиться в мир классов и объектов.

Мы просто обсуждали некоторые аспекты C++ и объектно-ориентированного программирования за обедом, кто-то (на самом деле великий инженер) сказал, что если у вас не будет действительно сильного опыта программирования до того, как вы изучите C++, это буквально погубит вас.

Я настоятельно рекомендую сначала выучить другой язык, а затем перейти на C++, когда он вам понадобится. В указателях нет ничего особенного, это просто рудиментарный кусок, оставшийся с тех времен, когда компилятору было сложно эффективно преобразовывать операции в сборку без них.

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

Пожалуйста, не поймите меня неправильно, я не говорю, что C++ ужасен или что-то в этом роде, и не хочу начинать пропагандистскую дискуссию, я использовал его и сейчас время от времени использую, я просто рекомендую вам начать с чего-то другого .

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

[править] просматривая последний абзац - я думаю, что это была моя самая точная аналогия!

какие языки вы предлагаете выучить в первую очередь? будет ли питон хорошим выбором? В настоящее время я пытаюсь изучить php, а также C++, синтаксически они очень похожи.

timmyg 19.09.2008 07:13

C# и Java хороши тем, что они проверяются во время компиляции, и, честно говоря, это действительно хорошая привычка. Если вы хотите просто пошалить, Python подойдет. Если вы делаете веб-сайт, Ruby on Rails - точка.

Bill K 19.09.2008 20:44

Да, и если вы ДЕЙСТВИТЕЛЬНО хотите изучить новейшие концепции программирования, посмотрите на Scala. Честно говоря, это может быть лучшим из всех концепций, которые он предлагает вам сразу. Hascal и Lisp также известны тем, что преподают хорошие концепции программирования.

Bill K 19.09.2008 20:46

Изучите язык ассемблера, а затем изучите C. Тогда вы узнаете, каковы основные принципы работы машины (и приведенные выше указатели).

Указатели и классы - фундаментальные аспекты C++. Если вы их не понимаете, значит, вы действительно не понимаете C++.

Лично я отказывался от C++ в течение нескольких лет, пока не почувствовал, что у меня есть твердое представление о C и о том, что происходит под капотом на языке ассемблера. Хотя это было довольно давно, теперь я думаю, что понимание того, как работает компьютер на низком уровне, действительно помогло моей карьере.

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

Классы относительно легко усвоить; ООП может занять много лет. Лично я не полностью понимал истинное ООП до прошлого года. Жаль, что Smalltalk не так широко распространен в колледжах, как следовало бы. Это действительно указывает на то, что ООП - это сообщения об обмене объектами, а не классы, являющиеся самодостаточными глобальными переменными с функциями.

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

Нет замены практике.

Легко прочитать книгу или послушать лекцию и почувствовать, что вы следите за происходящим.

Я бы порекомендовал взять некоторые примеры кода (я предполагаю, что они есть где-то на диске), скомпилировать и запустить их, а затем попытаться изменить их, чтобы сделать что-то другое.

  • Добавить еще один подкласс в иерархию
  • Добавить метод в существующий класс
  • Измените алгоритм, который повторяет вперед по коллекции идти наоборот.

Я не думаю, что есть какая-то «серебряная пуля», которая сможет это сделать.

Для меня указатели означали работу в сборке и то, что я видел, что указатель на самом деле был просто адресом, и что наличие указателя не означало, что то, на что он указывает, было значимым объектом.

Точка, в которой я действительно получил указатели, заключалась в кодировании TurboPascal на FatMac (около 1984 года или около того), который в то время был родным языком Mac.

У Mac была странная модель памяти, в соответствии с которой при выделении адреса память сохранялась в указателе в куче, но ее расположение не было гарантировано, и вместо этого процедуры обработки памяти возвращали указатель на указатель, называемый дескриптором. . Следовательно, чтобы получить доступ к любой части выделенной памяти, необходимо было дважды разыменовать дескриптор. На это потребовалось время, но постоянная практика в конечном итоге привела к уроку.

Обработку указателей в Паскале легче понять, чем в С ++, где синтаксис не помогает новичку. Если вы действительно застряли в понимании указателей в C, то лучшим вариантом может быть получение копии компилятора Pascal и попытка написать в нем некоторый базовый код указателя (Pascal достаточно близок к C, вы получите основы через несколько часов ). Связанные списки и тому подобное было бы хорошим выбором. Как только вы освоитесь с этим, вернетесь к C++ и усвоите концепции, вы обнаружите, что обрыв не будет выглядеть таким крутым.

В некотором смысле, вы можете рассматривать «указатели» как один из двух наиболее фундаментальных типов программного обеспечения (второй - «значения» (или «данные»)), которые существуют в огромном блоке однозначно адресуемых ячеек памяти. Подумай об этом. Объекты, структуры и т. д. На самом деле не существуют в памяти, существуют только значения и указатели. Фактически, указатель - это тоже значение ... значение адреса памяти, который, в свою очередь, содержит другое значение ... и так далее.

Итак, в C / C++, когда вы объявляете int (intA), вы определяете 32-битный фрагмент памяти, который содержит значение - число. Если вы затем объявляете «указатель на int» (intB), вы определяете 32-битный фрагмент памяти, который содержит адрес типа int. Я могу назначить последний, чтобы он указывал на первый, указав «intB = & intA», и теперь 32 бита памяти, определенные как intB, содержат адрес, соответствующий местоположению intA в памяти.

Когда вы «разыменовываете» указатель intB, вы смотрите на адрес, хранящийся в памяти intB, находите это место, а затем смотрите на хранимое там значение (число).

Обычно я сталкиваюсь с недоумением, когда люди теряют из виду, с чем именно они имеют дело, когда используют операторы «&», «*» и «->» - это адрес, значение или что-то в этом роде? Вам просто нужно сосредоточиться на том факте, что адреса памяти - это просто местоположения, а значения - это двоичная информация, хранящаяся там.

Вы читали Язык программирования C++ Бьярна Страуструпа? Он создал C++.

C++ FAQ Lite тоже хорош.

Вот моя аналогия для указателей и классов. Я воспользуюсь колодой карт. Колода карт имеет номинал и вид (9 червей, 4 пик и т. д.). Итак, в нашем C++ подобном языке программирования «Колода карт» мы скажем следующее:

HeartCard card = 4; // 4 of hearts!

Теперь вы знаете, где находится четверка червей, потому что, черт возьми, вы держите колоду лицом вверх в руке, и она находится наверху! Итак, что касается остальных карт, мы просто скажем, что четверка червей находится в НАЧАЛЕ. Итак, если бы я спросил вас, какая карта в НАЧАЛЕ, вы бы сказали: «Четверка червей, конечно!». Что ж, вы просто "указали" мне, где карточка. На нашем языке программирования "Колода карт" вы могли бы с таким же успехом сказать следующее:

HeartCard card = 4; // 4 of hearts!
print &card // the address is BEGINNING!

Теперь переверните свою колоду карт. Обратная сторона теперь НАЧАЛО, и вы не знаете, что это за карта. Но, допустим, вы можете делать все, что захотите, потому что вы полны магии. Давайте сделаем это на нашем языке "Колода карт"!

HeartCard *pointerToCard = MakeMyCard( "10 of hearts" );
print pointerToCard // the value of this is BEGINNING!
print *pointerToCard // this will be 10 of hearts!

Что ж, MakeMyCard («10 червей») - это вы творили свою магию и зная, что хотите указать на НАЧАЛО, сделав карту 10 червей! Вы переворачиваете карту и вуаля! Теперь * может сбить вас с толку. Если да, проверьте это:

HeartCard *pointerToCard = MakeMyCard( "10 of hearts" );
HeartCard card = 4; // 4 of hearts!
print *pointerToCard; // prints 10 of hearts
print pointerToCard; // prints BEGINNING
print card; // prints 4 of hearts
print &card; // prints END - the 4 of hearts used to be on top but we flipped over the deck!

Что касается классов, мы использовали классы в примере, определив тип как HeartCard. Мы знаем, что такое HeartCard ... Это карта со значением и типом сердца! Итак, мы классифицировали это как HeartCard. В каждом языке есть похожий способ определения или «классификации» того, что вы хотите, но все они разделяют одну и ту же концепцию! Надеюсь, это помогло ...

Это была довольно паршивая аналогия.

FlySwat 19.09.2008 02:30

Вы можете найти этот статья Джоэла поучительным. Кстати, если вы «какое-то время работали с C++» и закончили CS, возможно, вы пошли в школу JavaSchool (я бы сказал, что вы вообще не работали с C++; вы работал на C, но использовал компилятор C++).

Кроме того, просто чтобы поддержать ответы hojou и nsanders, указатели очень важны для C++. Если вы не понимаете указатели, значит, вы не понимаете основ C++ (кстати, признание этого факта - начало понимания C++). Точно так же, если вы не понимаете классы, значит, вы не понимаете основ C++ (или объектно-ориентированного программирования, если на то пошло).

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

Что касается классов (и объектно-ориентированного программирования в целом), я бы порекомендовал последнюю версию Stroustrups "Язык программирования C++". Это не только канонический справочный материал по C++, но и довольно много материала по множеству других вещей, от базовых объектно-ориентированных иерархий классов и наследования до принципов проектирования в больших системах. Это очень хорошее чтение (если не сказать немного толстое и краткое в пятнах).

lol, я только что прочитал ту статью Джоэла, и именно поэтому я пришел сюда и стал искать вопросы о указателях.

Spidey 19.10.2009 14:08

Понимание указателей в C / C++

Прежде чем можно будет понять, как работают указатели, необходимо понять, как переменные хранятся и доступны в программах. Каждая переменная состоит из 2 частей: (1) адрес памяти, где хранятся данные, и (2) значение сохраненных данных.

Адрес памяти часто называют l-значением переменной, а значение хранимых данных - r-значением (l и r означают левое и правое).

Рассмотрим утверждение:

int x = 10;

Внутренне программа связывает адрес памяти с переменной x. В этом случае предположим, что программа назначает x для размещения по адресу 1001 (не реалистичный адрес, но выбранный для простоты). Следовательно, lvalue (адрес памяти) x равен 1001, а rvalue (значение данных) x равно 10.

Доступ к rvalue осуществляется простым использованием переменной «x». Для доступа к lvalue необходим оператор «адрес» («&»). Выражение «& x» читается как «адрес x».

Expression          Value
----------------------------------
x                   10
&x                  1001

Значение, хранящееся в x, может быть изменено в любое время (например, x = 20), но адрес x (& x) никогда не может быть изменен.

Указатель - это просто переменная, которую можно использовать для изменения другой переменной. Он делает это, имея адрес памяти для своего rvalue. То есть он указывает на другое место в памяти.

Создание указателя на «x» выполняется следующим образом:

int* xptr = &x;

«Int *» сообщает компилятору, что мы создаем указатель на целочисленное значение. Часть «= & x» сообщает компилятору, что мы присваиваем адрес x значению r значения xptr. Таким образом, мы сообщаем компилятору, что xptr «указывает на» x.

Если предположить, что xptr назначен адресу памяти 1002, тогда память программы может выглядеть так:

Variable    lvalue    rvalue
--------------------------------------------
x           1001      10   
xptr        1002      1001

Следующий фрагмент головоломки - «оператор косвенного обращения» (‘*’), который используется следующим образом:

int y = *xptr;

Оператор косвенного обращения указывает программе интерпретировать r-значение xptr как адрес памяти, а не как значение данных. То есть программа ищет значение данных (10), хранящееся по адресу, предоставленному xptr (1001).

Собираем все вместе:

Expression      Value
--------------------------------------------
x                   10
&x                  1001
xptr                1001
&xptr               1002
*xptr               10

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

int x = 10;
int *xptr = &x;

printf("x = %d\n", x);
printf("&x = %d\n", &x);        
printf("xptr = %d\n", xptr);
printf("*xptr = %d\n", *xptr);

*xptr = 20;

printf("x = %d\n", x);
printf("*xptr = %d\n", *xptr);

Для вывода вы увидите (Примечание: адрес памяти будет каждый раз отличаться):

x = 10
&x = 3537176
xptr = 3537176
*xptr = 10
x = 20
*xptr = 20

Обратите внимание, как присвоение значения «* xptr» изменило значение «x». Это связано с тем, что «* xptr» и «x» относятся к одному и тому же месту в памяти, что подтверждается тем, что «& x» и «xptr» имеют одинаковое значение.

lvalues ​​и rvalues ​​не имеют ничего общего с адресами памяти.

Puppy 05.11.2010 18:15

Я смущен b / c для вывода, вы говорите x = 10, но затем на 3 строки вы говорите x = 20? Эта переменная x не может иметь одновременно два значения, правильно?

Robert Houghton 19.08.2019 21:45

Указатели - это не какая-то магия, вы их постоянно используете!
Когда вы говорите:

int a;

а компилятор создает хранилище для 'a', вы фактически говорите, что объявляете
an int и хотите назвать его ячейку памяти 'a'.

Когда вы говорите:

int * a;

вы объявляете переменную, которая может содержать ячейку памяти типа int. Это так просто. Также не бойтесь арифметики указателей, просто всегда Имейте в виду "карту памяти", когда вы имеете дело с указателями и думаете в терминах прохождения адресов памяти.

Классы в C++ - это всего лишь один из способов определения абстрактных типов данных. Я бы посоветовал прочитать хорошую книгу по ООП, чтобы понять эту концепцию, а затем, если вам интересно, узнать, как компиляторы C++ генерируют код для имитации ООП. Но эти знания придут со временем, если вы будете достаточно долго придерживаться C++ :)

Кажется, ваша проблема заключается в ядре C в C++, а не в самом C++. Купите себе Керниган и Ричи (Язык программирования C). Вдохните это. Это очень хороший материал, одна из лучших когда-либо написанных книг по языку программирования.

В случае с классами у меня было три метода, которые действительно помогли мне перейти к настоящему объектно-ориентированному программированию.

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

Второе, что помогло, было в моем классе системного анализа, где мне пришлось создавать http://www.agilemodeling.com/artifacts/classDiagram.htm"> диаграммы классов UML. Они, которые я только что действительно нашел, помогли мне понять структуру классов. в программе.

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

Мой лучший совет: это требует большой практики, и чем больше вы программируете, тем лучше вы это поймете.

Другие вопросы по теме