Путаница с указателями и их адресами памяти - PullRequest
0 голосов
/ 11 июня 2010

хорошо, я смотрю на код здесь, и идею трудно понять.

#include <iostream>
using namespace std;
class Point
{
public :
    int X,Y;
    Point() : X(0), Y(0) {}
};

void MoveUp (Point * p)
{
    p -> Y += 5;
}

int main()
{
    Point point;
    MoveUp(&point);
    cout << point.X << point.Y;
    return 0;
}

Хорошо, поэтому я считаю, что класс создан и X и Y объявлены, и они помещены в конструктор

метод создан и аргумент - Point * pчто означает, что мы собираемся вставить указатель конструктора в функцию;

теперь мы создаем объект с именем point, затем вызываем наш метод и помещаем в него адрес указателей?просто номер памяти, как 0x255255?

и почему p никогда не было объявлено?

(int * p = Y)

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

Ответы [ 6 ]

9 голосов
/ 11 июня 2010

p было объявлено .

void MoveUp (Point * p)
{
    p -> Y += 5;
}

- это функция, которая берет указатель на Point и добавляет 5 к его значению Y.Это ничем не отличается от следующего:

void f(int n) {
    printf ("%d\n", n);
}
:
int x = 7;
f(x);

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

Возможно, некоторые комментарии в коде помогут:

#include <iostream>
using namespace std;
class Point
{

public :
    int X,Y;
    Point() : X(0), Y(0) {}       // Constructor sets X and Y to 0.
};

void MoveUp (Point * p)           // Take a Point pointer p.
{
    p -> Y += 5;                  // Add 5 to its Y value.
}
int main()
{
    Point point;                  // Define a Point.
    MoveUp(&point);               // Call MoveUp with its address.
    cout <<point.X << point.Y;    // Print out its values (0,5).
    return 0;
}

Указатели - это просто уровень косвенности.В коде:

1   int X;
2   int *pX = &X;
3   X = 7;
4   *pX = 7;

эффект строк 3 и 4 идентичен.Это потому, что pX является указателем на X, поэтому *pX, содержимое pX, фактически X.

В вашем случае p->Y совпадает с (*p).Y или Y член класса, на который указывает p.

3 голосов
/ 11 июня 2010

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

Тип указателя (например, char *, int *, Point*) просто сообщает компилятору, что хранится по этому адресу памяти.

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

и почему p никогда не объявлялось?

pобъявляется:

//p is declared to be a variable that holds an address
// and at that address it holds a type Point
//p itself only holds an address not the actual data of the Point.
void MoveUp (Point * p)
{
  //The -> operator when applied to a pointer, means give me the object at
  // that address and then access the following member
  p->Y += 5;
}

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

Вы можете думать об адресе памяти просто как о числе.В 32-битных программах это число составляет 4 байта.В 64-битных программах это число имеет длину 8 байт.


Рассмотрим следующий код:

Point point;
Point *p = &point;

Переменная point имеет тип Point.Он содержит объект класса Point.
. Выражение &point возвращает адрес переменной Point point.Выражение &point имеет тип Point*.
Переменная p содержит адрес типа Point, тип p равен Point*.p хранит адрес в памяти объекта point.

1 голос
/ 11 июня 2010

Думайте о памяти как о смежных маленьких блоках.

Теперь представьте, что класс Point имеет ширину 2 блока, и вы помещаете его в любое место памяти. Неважно, где, важно то, что он находится только в ОДНОЙ начальной точке. Вы можете переместить его и изменить эту начальную точку, но безвозвратно начнете в ОДНОЙ начальной точке.

Тогда указатель - это номер ОДНОЙ начальной точки.

Когда вы передаете указатель в качестве аргумента, вы делаете

  • ты: «Эй, возьми, возьми эту точку и делай, что знаешь!»
  • функция: «хорошо, но где находится точка!?»
  • ты: «о, прости, я не беру это с собой, он находится там, в этом квартале!»

И теперь функция будет знать, что ТАМ это Point, и с помощью магии компилятора функция будет знать, что ее ширина составляет 2 блока. Затем функция берет его, изменяет свой Y (спасибо еще раз, компилятор) и оставляет его там, где он был раньше (на самом деле, он даже не забрал его оттуда). Через несколько минут вы идете туда и видите, что Point.Y изменился. Вы говорите «спасибо», и вы идете.

1 голос
/ 11 июня 2010

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

класс создан и X и Y объявлены, и они помещены в Конструктор

показывает необходимость такого разъяснения. Вот обсуждение книг, которые вы можете прочитать: Книги, на которые можно ссылаться для изучения ООП с помощью C ++

1 голос
/ 11 июня 2010

p объявлено в определении функции

void MoveUp (Point * p)
0 голосов
/ 11 июня 2010

p был объявлен как параметр метода.

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

int i = 5;    //int
int *pointer; //int pointer

pointer = &i; //sets pointer to the memory address of i

doMath(&i); //passes a memory address, value inside that address is being used
doMath(pointer); //same as above
dontMath(i); //value of x will be 207, value of i is still 7 since a copy is being modified

//value of pointer is a memory address
//value of *pointer is the value stored inside that memory address, 7
//value of &pointer is the memory address of pointer, which itself holds the memory address


void doMath(int *p) {
   *p++; 
}
void dontMath(int x){
   x=x+200;
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...