Указатель не прокручивает объекты должным образом - PullRequest
0 голосов
/ 02 апреля 2020

Я студент университета и пытаюсь выполнить упражнение C ++, данное мне профессором. Я извиняюсь за мой английский sh. Короче говоря, мне нужно управлять определенным количеством объектов (одного типа) без использования массивов, а только с помощью указателей. Рассматриваемые объекты являются объектами типа «Дом».

Я создаю указатель на «Дом» и с помощью oop указываю указатель на новый объект типа «Дом», инициализированный переменными, введенными пользователь. Затем я перемещаю указатель и начинаю снова.

House* housePtr;

cout<<"We start building houses, you will have to build 4.\n";

for (auto i=0; i<4; ++i, ++housePtr)
{
    int r, d;

    cout<<"\nLet's build the number "<<i+1<<endl;
    cout<<"How many rooms must it have?\n";
    cin>>r;
    cout<<"\nHow far is it from the center?\n";
    cin>>d;

    housePtr= new House(r, d);

}

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

Предыдущее значение для l oop оставляет указатель на позицию рядом с последним созданным объектом. Таким образом, с помощью для l oop я возвращаю указатель на первый объект (поэтому я делаю его go 4 шага назад), и на каждой итерации я заставляю его печатать адрес памяти, удерживаемый указателем, то есть память адрес каждого дома.

for (auto i=0; i<4; i++, housePtr--)
{
    cout<<endl<<housePtr<<endl;
}

И это вывод этого последнего фрагмента кода:

0x10139c

0x101390

0x101384

0x101378

Первый - это адрес, который не имеет ничего общего с объектами, потому что он тот, который присущ позиции после последнего объекта. Другие 3 следующие (согласно моей логике c) адреса четвертого, третьего и второго домов соответственно.

Снова взяв указатель, для каждого объекта я напечатал его значения, а также адрес

for (auto i=0; i<4; housePtr++, i++)
{
    cout<<"\nThe house "<<i+1<<" has "<<housePtr->getNumOfRooms()<<" rooms and is ";
    cout<<housePtr->getDistanceFromCenter()<<" meters from the center\n";
    cout<<housePtr<<endl;
}

И это вывод:

The house 1 has 190607135 rooms and is 201338508 meters from the center
0x10136c

The house 2 has 7 rooms and is 4 meters from the center
0x101378

The house 3 has 190607135 rooms and is 201338508 meters from the center
0x101384

The house 4 has 5 rooms and is 8 meters from the center
0x101390

Начальные вводимые мной значения:

We start building houses, you will have to build 4.

Let's build the number 1
How many rooms must it have?
8

How far is it from the center?
7

Let's build the number 2
How many rooms must it have?
5

How far is it from the center?
8

Let's build the number 3
How many rooms must it have?
7

How far is it from the center?
4

Let's build the number 4
How many rooms must it have?
5

How far is it from the center?
8

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

В чем проблема?

Ответы [ 2 ]

0 голосов
/ 02 апреля 2020

Увеличение указателя, который не является массивом, приведет к тому, что этот указатель будет указывать на неиспользуемую / недействительную память, что вызывает неопределенное поведение (именно поэтому вы получаете странные значения). Кроме того, перезапись указателя new каждый раз приведет к утечке памяти. По сути, вы используете указатель, как если бы он был массивом, хотя это не так. Если вам всегда нужно сделать 4 House -объектов, сделайте это следующим образом:

House* housePtr1;
House* housePtr2;
House* housePtr3;
House* housePtr4;

cout<<"We start building houses, you will have to build 4.\n";

int r, d;

cout<<"\nLet's build the number 1"<<endl;
cout<<"How many rooms must it have?\n";
cin>>r;
cout<<"\nHow far is it from the center?\n";
cin>>d;

housePtr1 = new House(r, d);



cout<<"\nLet's build the number 2"<<endl;
cout<<"How many rooms must it have?\n";
cin>>r;
cout<<"\nHow far is it from the center?\n";
cin>>d;

housePtr2 = new House(r, d);



cout<<"\nLet's build the number 3"<<endl;
cout<<"How many rooms must it have?\n";
cin>>r;
cout<<"\nHow far is it from the center?\n";
cin>>d;

housePtr3 = new House(r, d);



cout<<"\nLet's build the number 4"<<endl;
cout<<"How many rooms must it have?\n";
cin>>r;
cout<<"\nHow far is it from the center?\n";
cin>>d;

housePtr4 = new House(r, d);

И затем выведите значения:

cout<<"\nThe house 1 has "<<housePtr1->getNumOfRooms()<<" rooms and is ";
cout<<housePtr1->getDistanceFromCenter()<<" meters from the center\n";
cout<<housePtr1<<endl;

cout<<"\nThe house 2 has "<<housePtr2->getNumOfRooms()<<" rooms and is ";
cout<<housePtr2->getDistanceFromCenter()<<" meters from the center\n";
cout<<housePtr2<<endl;

cout<<"\nThe house 3 has "<<housePtr3->getNumOfRooms()<<" rooms and is ";
cout<<housePtr3->getDistanceFromCenter()<<" meters from the center\n";
cout<<housePtr3<<endl;

cout<<"\nThe house 4 has "<<housePtr4->getNumOfRooms()<<" rooms and is ";
cout<<housePtr4->getDistanceFromCenter()<<" meters from the center\n";
cout<<housePtr4<<endl;

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

0 голосов
/ 02 апреля 2020

Здесь, когда вы делаете housePtr = новый дом (r, d); , будет создан новый объект и housePtr будет указывать на это. Теперь, когда вы выполните housePtr ++ , оно будет увеличено на размер класса House. Теперь снова, когда вы делаете housePtr = new House (r, d); новый объект будет создан и не обязательно будет последовательным адресом ранее созданного объекта. Это самая важная вещь в C ++. C ++ обеспечит вам свободную память безотносительно к безопасности. Это огромная сила, и как говорит человек-паук: «С великой силой приходит большая ответственность». Здесь вы всегда должны будете гарантировать, что когда бы вы ни создавали объект динамически, всегда сохраняйте указатель на этот объект. В противном случае вы никогда не получите этот адрес обратно. И это действительно огромная проблема под названием утечка памяти .

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

...