Kolejki - kilka pytań

0

Witam. Prosiłbym o pomoc z kilkoma rzeczami.
Przede wszystkim - co najbardziej mi "mąci" - po zaalokowaniu do wskaźnika pamięci dynamicznej, można ją zaalokować jeszcze raz na wskaźnik o tej samej nazwie. Co w konsekwencji taki wskaźnik zawiera? Zamieszczam fragment kodu. Kłóci mi się to z logiką programowania - otóż czy dochodzi wtedy do nadpisania? Przecież z samej definicji wskaźnik zawiera jeden adres określonego obiektu (chyba, że mylnie ją interpretuję) - więc czy w tym wypadku zawierałby kilka adresów do poszczególnych obiektów?

 #include <iostream>
#include <cstring>
using namespace std;

struct student
{
	string imie, nazwisko;
	int numer;
	student *next;
};

int main ()
{
	student* add = new student;
	student *add = new student;
	student *add = new student;

        delete add;

	system ("pause");
	return 0;
}

To pierwsza rzecz. Druga: Co oznacza taki zapis? Mogę zamieścić na wszelki wypadek także cały kod kolejki.

struct person
{
	string name,surname;
	person *next;
};

struct queue
{
	person *head; 
	person *end;
};
int main ()
{
person * add = new person;
Queue.end->next = add;
} 

Chodzi mi o ostatnią linijkę - następują wskazania na poszczególne obiekty, ale nie do końca to rozumiem. Pozdrawiam

1
  1. Ten pierwszy kod to wyciek pamięci ;] Jest tak jak piszesz - wskaźnik trzyma JEDEN adres. Przypisanie nowego adresu powoduje utratę starego.
  2. Poczytaj o tym jak działa lista jedno/dwukierunkowa. Po prostu masz elementy które nie tlyko przechowują "wartość" ale też mają wskazanie na następny element. Trochę jak pociąg.
0

W porządku, dzięki wielkie. Jednak w programie na lekcji coś takiego było zawarte w funkcji, jak powyżej - zamieszczam fragment kodu i prosiłbym o analizę tego zapisu w jednej z funkcji -

student *add = new student;
#include <iostream>
#include <cstring>
#include <string>
using namespace std;

struct person
{
	string name,surname;
	person *next;
};

struct queue
{
	person *head; 
	person *end;
};
//dodawanie
void addPerson (person *add)
{

	cout << "Wprowadz imie: " << "\t";
	cin >> add->name;
	cout << endl;
	cout << "Wprowadz nazwisko: " << "\t";
	cin >> add->surname;
	cout << endl;
	add->next = nullptr; // wskaznik jako pusty

}

void addToQueue (queue &Queue)
{
	person * add = new person;
	addPerson(add);
	Queue.end=Queue.head;
	if (Queue.head == nullptr)
	{
		Queue.head = Queue.end = add;
	}

	else{
		while (Queue.end->next != nullptr)
		{
			Queue.end = Queue.end -> next;
		}
		Queue.end->next = add; 
		Queue.end = add;
	}
}
//wyswietlanie

void showPerson (person Person)
{
	cout << "Imie : " << "\t" << Person.name << endl;
	cout << "Nazwisko : " << "\t" << Person.surname << endl << endl;
}

void showQueue (queue Queue)
{
	person *live = Queue.head;
	if (live == nullptr)
	{
		cout << "Kolejka jest pusta. \n"; system ("pause"); return;
	}

	else 
		while (live !=nullptr)
		{
			showPerson (*live);
			live = live->next;
		}

		system ("pause");
}

void deleted(queue &Delete)
{
	if (Delete.head == nullptr) 
	{
		cout << "Nie ma co usunac, kolejka pusta.";
		system("PAUSE");
		return;
	}
	person *deleted = Delete.head;
	Delete.head = Delete.head->next;
	delete deleted;
}

int main ()
{
	queue Queue;
	Queue.head = nullptr;
	Queue.end = Queue.head;
	short set = 6;
	while (set != 4)
	{
		set=6;
		while (set > 4)
		{
		system("cls");
		cin.clear();
		cin.sync();
		cout << "1 - Dodaj" << endl << "2 - Wyswietl kolejke" << endl << "3 - Usun" << endl << "4 - Zakoncz" << endl;
		cin >> set;
		}

		switch (set)
		{
		case 1: addToQueue(Queue); break;
		case 2: showQueue(Queue);  break;
		case 3: deleted(Queue); break;
		case 4: break;
		default:
			break;
		}
	}
	return 0;
}
1

Ale przecież ten kod nie ma nic wspólnego z tym o czym pisałeś wcześniej! Tutaj alokujesz pamięć wewnątrz funkcji do pewnej tymczasowej zmiennej a potem ZAPAMIĘTUJESZ adres zaalokowanej pamięci na końcu kolejki. Ergo nic nie jest tracone.

0

W porządku, ale kiedy tą funkcję wywołam kilkukrotnie - co się dzieje z adresem, na który wskazuje ponownie zainicjalizowany wskaźnik add? To jest dla mnie niejasne i właściwie uniemożliwia mi zrozumienie działania tej kolejki.

0

o_O Ale jakie to ma znaczenie? Zresztą po wyjściu z funkcji wszystkie jej lokalne zmienne giną, wiec taka dywagacja nie ma w ogóle sensu. Ale chyba rozumiem gdzie leży twój problem. Tobie się wydaje że pamięć jest jakoś związana ze wskaźnikiem do którego została przypisana, a to bzdura.
Wskaźnik jest zmienna liczbowa (zwykle 32 bitowy int) która przechowuje pewną liczbę, nic więcej. Alokacja pamięci oznacza pewien obszar pamięci jako zajęty i zwraca adres (czyli liczbę) tego obszaru. Możesz dla ułatwienia uznać że adres w pamięci to jest numer komórki pamięci. Ten numer przypisujesz do wskaźnika. To jest jedna liczba, nic więcej. I tą liczbę mozesz przypisać sobie do typu zmiennych do ilu chcesz, tak samo jak liczbę 1 możesz przypisać do 100 różnych zmiennych. Zaalokowany obszar pamięci nie jest w żaden sposób związany ze wskaźnikiem do którego go przypisano przy alokacji.

Dostajesz po prostu informację że np. komórka pamięci o numerze 1234 została zaalokowana. I tą informację możesz sobie zapisać w 100 róznych zmiennych jak lubisz, wystarczy że wpiszesz do nich numerek 1234. Ale to nie znaczy że zmienna (wskaźnik) do której przypisałeś numerek 1234 nie moze zostać ponownie użyta, bo może. To jest taka sytuacja:

int zmienna1 = 10;
int zmienna2 = zmienna1;
zmienna1 = 20;

I teraz ty się pytasz "co się stanie z 10 w takiej sytuacji?". A odpowiedź jest prosta - nic się nie stanie...

0

Chyba już rozumiem. Więc jako że wskaźnik add jest lokalny - ginie po zakończeniu funkcji i zaczyna "żyć" na nowo, kiedy ponownie ją (funkcję) wywołujemy. To jednak nie dzieje się z pamięcią, która jest każdorazowo przypisywana do tego wskaźnika na czas trwania tej funkcji - pamięć istnieje niezależnie od niego i mamy do niej w każdym momencie dostęp poprzez wskaźniki z pól struktur, do których został przypisany tymczasowy, każdorazowy dla każdego wywołania funkcji wskaźnik add. Tak?

1

Tak, dokładnie tak.

0

W porządku, dzięki - pozdrawiam :). Więc na czas wywołania funkcji alokuje się coraz to nowsza pamięć, np. kolejno: 1234, 1557, 1235, następnie te adresy są przypisywane do wskaźników ze struktur, tak?

0

Tak. I potem przechodząc sobie po kolei po elementach tych struktur możemy odczytywać dane które znajdują się w tych zaalokowanych obszarach.

1 użytkowników online, w tym zalogowanych: 0, gości: 1