Trouble with passing class objects by reference

Dec 9, 2014 at 2:45am
Hi, I am working on a program to simulate a zoo, essentially there are passengers that are waiting for a ride in cars around the zoo. This is a multi-threaded program using the std::thread class, and essentially I pass an array of passengers and an array of cars into a function as a thread is initialized, then based on some the values of the objects, I place cars and passengers each into a std::queue. Then each passenger is paired with a car until one of the queues is empty. There is much more to the program than this, but I think this is enough to show the problem I am having.

The problem is that when I modify the member variables of the "front" member of each queue, the values don't stick when I access the values directly. You can see in the code below that I try to print the value

Here is the header of the function that the next code snippets are from.
void carsManage(int time, car cars[], gasStation& station, visitor visitors[], int numVisitors, int numPumps, int numCars, int rideTime)

here you can see the queues are initialized and filled with certain objects
1
2
queue<visitor> rideQueue;
	queue<car> carQueue;


1
2
3
4
5
6
7
8
9
10
11
for (int i = 0; i < numVisitors; i++)//checking for visitors that need rides
	{
		if (!visitors[i].getRidden())
			rideQueue.push(visitors[i]);
	}

	for (int i = 0; i < numCars; i++)//adding all ready cars to queue
	{
		if (cars[i].getReady())
			carQueue.push(cars[i]);
	}


In the code below there are two std::cout statements that should return the same values for each object, but they do not.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
while (rideQueue.size() > 0 && carQueue.size() > 0)//putting drivers in cars until one runs out
	{
		rideQueue.front().setRidden(true);
		rideQueue.pop();
		carQueue.front().setRides(carQueue.front().getRides() - 1);
		carQueue.front().setReady(false);
		carQueue.front().setLeaveTime(time);
		cout << carQueue.front().getLeaveTime() << "\n";
		carQueue.pop();
	}
	int carsOut = 0;
	
	for (int i = 0; i < numCars; i++)//calculating cars out driving
	{
		cout << cars[i].getLeaveTime() << "\n";
		if (cars[i].getLeaveTime() <= time && cars[i].getLeaveTime() > 0)
			carsOut += 1;
	}


also, here is the thread initialization, if that helps clarify anything

thread carAgent(carsManage, time, cars, ref(station), visitors, numVisitors, numPumps, numCars, rideTime);

If anything needs to be clarified, let me know; Any help would be greatly appreciated.
Last edited on Dec 9, 2014 at 3:29am
Dec 9, 2014 at 4:00am
Alright after doing a lot of debugging I narrowed it down to the queue class. Apparently, modifying the front element of the queue class isn't done by reference, so idk what to do about that.
Dec 9, 2014 at 4:05am
Is there a way to push an object into a queue by reference?
Dec 9, 2014 at 4:08am
std::queue::front returns by reference.

I'm not really sure what your code does, but this looks highly suspicious to me:
3
4
5
6
7
8
9
		rideQueue.front().setRidden(true);
		rideQueue.pop();
		carQueue.front().setRides(carQueue.front().getRides() - 1);
		carQueue.front().setReady(false);
		carQueue.front().setLeaveTime(time);
		cout << carQueue.front().getLeaveTime() << "\n";
		carQueue.pop();
Why set all that information and then destroy it? Do you understand what pop() does?
Last edited on Dec 9, 2014 at 4:09am
Dec 9, 2014 at 4:36am
Well this particular thread is generated many times in the loop, so the queue itself is populated and depopulated with every iteration. That's not the problem though. And yeah I know front returns the reference, but the problem I am having is that push does not actually pass by reference, rather by value. If you know a way to fix this, that would be awesome, but either way thank you for the response.
Dec 9, 2014 at 5:29am
tmorlan wrote:
Is there a way to push an object into a queue by reference?
Maybe you want to use emplace?

http://www.cplusplus.com/reference/queue/queue/emplace/

I'm not sure why you are asking for what you are asking for. If an object is not in a container, there's no way to ever make that object be in that container. You would work around this by using e.g. smart pointers wrapper classes such as std::unique_ptr so that the object is persistent but the wrapper class that holds it can be juggled around, but you may want to reconsider your design.
Dec 9, 2014 at 5:55am
I think the problem is that you want to store a reference to an existing object in your containers, and you can't do that directly. Consider storing a std::reference_wrapper or a pointer to the object instead.

http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper

Dec 9, 2014 at 6:13am
Thanks for the responses guys. cire, you were right, that was the issue and making the queue of objects a queue of object pointers solved it. I know my design is sh*t, and I wish I could redesign it, but I'm just a lowly college student, and this is a project that was due yesterday. Thanks again!
Topic archived. No new replies allowed.