Referenz auf von new erstellten Speicher



  • Hallo ich lese grade denn C++ Primer Plus und bin im 12 Kapitel dort gibt es grade ein Code Beispiel. Dabei versteh ich eine Sache nicht. Ich Poste mal den Code und nehme die Stelle die ich nicht verstehe heraus. Hoffe ihr könnt mir da helfen.

    // queue.cpp -- Queue and Customer methods
    #include "queue.h"
    #include <cstdlib> // (or stdlib.h) for rand()
    // Queue methods
    Queue::Queue(int qs) : qsize(qs)
    {
    	front = rear = NULL; // or nullptr
    	items = 0;
    }
    Queue::~Queue()
    {
    	Node * temp;
    	while (front != NULL) // while queue is not yet empty
    	{
    		temp = front; // save address of front item
    		front = front->next;// reset pointer to next item
    		delete temp; // delete former front
    	}
    }
    bool Queue::isempty() const
    {
    	return items == 0;
    }
    bool Queue::isfull() const
    {
    	return items == qsize;
    }
    int Queue::queuecount() const
    {
    	return items;
    }
    // Add item to queue
    bool Queue::enqueue(const Item & item)
    {
    	if (isfull())
    		return false;
    	Node * add = new Node; // create node
    	// on failure, new throws std::bad_alloc exception
    	add->item = item; // set node pointers
    	add->next = NULL; // or nullptr;
    	items++;
    	if (front == NULL) // if queue is empty,
    		front = add; // place item at front
    	else
    		rear->next = add; // else place at rear
    	rear = add; // have rear point to new node
    	return true;
    }
    // Place front item into item variable and remove from queue
    bool Queue::dequeue(Item & item)
    {
    	if (front == NULL)
    		return false;
    	item = front->item; // set item to first item in queue
    	items--;
    	Node * temp = front; // save location of first item
    	front = front->next; // reset front to next item
    	delete temp; // delete former first item
    	if (items == 0)
    		rear = NULL;
    	return true;
    }
    // customer method
    // when is the time at which the customer arrives
    // the arrival time is set to when and the processing
    // time set to a random value in the range 1 - 3
    void Customer::set(long when)
    {
    	processtime = std::rand() % 3 + 1;
    	arrive = when;
    }
    
    // queue.h -- interface for a queue
    #ifndef QUEUE_H_
    #define QUEUE_H_
    // This queue will contain Customer items
    class Customer
    {
    private:
    	long arrive; // arrival time for customer
    	int processtime; // processing time for customer
    public:
    	Customer() { arrive = processtime = 0; }
    	void set(long when);
    	long when() const { return arrive; }
    	int ptime() const { return processtime; }
    };
    
    typedef Customer Item;
    
    class Queue
    {
    private:
    	// class scope definitions
    	// Node is a nested structure definition local to this class
    	struct Node { Item item; struct Node *next;};
    	enum {Q_SIZE = 10};
    	// private class members
    	Node * front; // pointer to front of Queue
    	Node * rear; // pointer to rear of Queue
    	int items; // current number of items in Queue
    	const int qsize; // maximum number of items in Queue
    	// preemptive definitions to prevent public copying
    	Queue(const Queue & q) : qsize(0) { }
    	Queue & operator=(const Queue & q) { return *this;}
    public:
    	Queue(int qs = Q_SIZE); // create queue with a qs limit
    	~Queue();
    	bool isempty() const;
    	bool isfull() const;
    	int queuecount() const;
    	bool enqueue(const Item &item); // add item to end
    	bool dequeue(Item &item); // remove item from front
    };
    #endif
    
    // bank.cpp -- using the Queue interface
    // compile with queue.cpp
    #include <iostream>
    #include <cstdlib> // for rand() and srand()
    #include <ctime> // for time()
    #include "queue.h"
    const int MIN_PER_HR = 60;
    bool newcustomer(double x); // is there a new customer?
    int main()
    {
    	using std::cin;
    	using std::cout;
    	using std::endl;
    	using std::ios_base;
    	// setting things up
    	std::srand(unsigned int(std::time(0))); // random initializing of rand()
    	cout << "Case Study: Bank of Heather Automatic Teller\n";
    	cout << "Enter maximum size of queue: ";
    	int qs;
    	cin >> qs;
    	Queue line(qs); // line queue holds up to qs people
    	cout << "Enter the number of simulation hours: ";
    	int hours; // hours of simulation
    	cin >> hours;
    	// simulation will run 1 cycle per minute
    	long cyclelimit = MIN_PER_HR * hours; // # of cycles
    	cout << "Enter the average number of customers per hour: ";
    	double perhour; // average # of arrival per hour
    		cin >> perhour;
    	double min_per_cust; // average time between arrivals
    	min_per_cust = MIN_PER_HR / perhour;
    	Item temp; // new customer data
    	long turnaways = 0; // turned away by full queue
    	long customers = 0; // joined the queue
    	long served = 0; // served during the simulation
    	long sum_line = 0; // cumulative line length
    	int wait_time = 0; // time until autoteller is free
    	long line_wait = 0; // cumulative time in line
    	// running the simulation
    	for (int cycle = 0; cycle < cyclelimit; cycle++)
    	{
    		if (newcustomer(min_per_cust)) // have newcomer
    		{
    			if (line.isfull())
    				turnaways++;
    			else
    			{
    				customers++;
    				temp.set(cycle); // cycle = time of arrival
    				line.enqueue(temp); // add newcomer to line
    			}
    		}
    		if (wait_time <= 0 && !line.isempty())
    		{
    			line.dequeue (temp); // attend next customer
    			wait_time = temp.ptime(); // for wait_time minutes
    			line_wait += cycle - temp.when();
    			served++;
    		}
    		if (wait_time > 0)
    			wait_time--;
    		sum_line += line.queuecount();
    	}
    	// reporting results
    	if (customers > 0)
    	{
    		cout << "customers accepted: " << customers << endl;
    		cout << " customers served: " << served << endl;
    		cout << " turnaways: " << turnaways << endl;
    		cout << "average queue size: ";
    		cout.precision(2);
    		cout.setf(ios_base::fixed, ios_base::floatfield);
    		cout << (double) sum_line / cyclelimit << endl;
    		cout << " average wait time: "
    			<< (double) line_wait / served << " minutes\n";
    	}
    	else
    		cout << "No customers!\n";
    
    	cout << "Done!\n";
    
    	cin.get();
    	cin.get();
    	return 0;
    }
    // x = average time, in minutes, between customers
    // return value is true if customer shows up this minute
    bool newcustomer(double x){
    	return (std::rand() * x / RAND_MAX  < 1);
    }
    
    bool Queue::dequeue(Item & item)
    {
    	if (front == NULL)
    		return false;
    	item = front->item; // set item to first item in queue
    	items--;
    	Node * temp = front; // save location of first item
    	front = front->next; // reset front to next item
    	delete temp; // delete former first item
    	if (items == 0)
    		rear = NULL;
    	return true;
    }
    

    Es also ich gib hier ja meiner Item & temp Referenz von der Main als Parameter(Argument). Dann bekommt es ja den Wert von front->item bloß dann wird die Speicherstelle die mit new erstellt wurde ja mit delete gelöscht. Warum kann ich dann trotzdem noch mit der Referenz drauf zugreifen? Wird der Wert kopiert ich hatte das so verstanden das eine Referenz nur ein Alias ist aber wovon ein Alias wenn das eigentlich schon gelöscht wurde?

    Da der Code funktioniert werde ich wohl irgendwas nicht verstanden haben aber was?



  • temp ist ein zeiger, keine referenz. zwischen den beiden dingen gibt es wichtige unterschiede. also wenn man etwas aus der queue (warteschlange) raus nimmt (vorne natürlich wie bei jeder warteschlange auch die vordersten leute zuerst bedient werden), dann ist ja das neue vorne der eintrag, der davor an zweiter stelle war. für mich sieht es so aus als wäre diese queue als single-linked-list implementiert worden. also ist der zweite eintrag = der nächste eintrag des ersten eintrages. logisch, oder? der zeiger temp merkt sich, wo im speicher das zweite element gespeichert ist (denn das weiss bis dahin nur das erste element, welches ja aus der queue genommen / gelöscht wird). dann kann man getrost das erste element löschen und das neue vorderste element wird das, auf welches der temporäre zeiger zeigt.

    ich hoffe, es ist einigermassen verständlich.

    frohe weihnachten!



  • Du meinst wahrscheinlich Item & item , nicht temp ?

    item = front->item; // kopiert front->item nach item
    

    Wenn Du dir item als Alias vorstellen willst ist es ein Alias für das der Funktion übergebene Objekt. Da es keine const Referenz ist kann dem Objekt ein neuer Wert zugewiesen werden.

    Vielleicht ist es einfacher sich eine Referenz als 'derefenzierter Zeiger' vorzustellen:

    bool Queue::dequeue(Item* item)
    {
        *item = front->item; // set item to first item in queue
    ...
    

    - osdt



  • CraftPlorer schrieb:

    Hallo ich lese grade denn C++ Primer Plus

    Niemals den Primer Plus lesen. Der hat mit dem echten Primer von Moo nichts zu tun.



  • Ok danke.
    Ist das der Kommentar von out ernst zu nehmen? Hab viel gutes zu den C++ Primer Plus gelesen.



  • CraftPlorer schrieb:

    Ist das der Kommentar von out ernst zu nehmen? Hab viel gutes zu den C++ Primer Plus gelesen.

    http://www.c-plusplus.net/forum/322530



  • out schrieb:

    CraftPlorer schrieb:

    Hallo ich lese grade denn C++ Primer Plus

    Niemals den Primer Plus lesen. Der hat mit dem echten Primer von Moo nichts zu tun.

    Ja. Es gibt leider relativ viele Bücher, die nichts taugen.



  • CraftPlorer schrieb:

    Ok danke.
    Ist das der Kommentar von out ernst zu nehmen? Hab viel gutes zu den C++ Primer Plus gelesen.

    Sry, wollte das hier zitieren. :p


Anmelden zum Antworten