Silly STL question...

J

Joe Van Dyk

#include <queue>
#include <string>
#include <iostream>

using namespace std;

class Foo
{
public:
string data;
};

class Holder
{
public:
void add_to_queue()
{
Foo f;
f.data = "Sup!";
holder.push(f); // Bad?
}
queue<Foo> holder;
};

int main()
{
Holder h;
h.add_to_queue();
h.add_to_queue();
return 0;
}

When I create a Foo object inside Holder::add_to_queue(), that's a
temporary variable. And then when I add it to the queue, isn't that
bad? Or does the push create a new copy of the Foo object and stick
that inside the queue?

(wondering if I should use pointers or references instead of objects)

Joe
 
M

mlimber

Joe said:
#include <queue>
#include <string>
#include <iostream>

using namespace std;

class Foo
{
public:
string data;
};

class Holder
{
public:
void add_to_queue()
{
Foo f;
f.data = "Sup!";
holder.push(f); // Bad?
}
queue<Foo> holder;
};

int main()
{
Holder h;
h.add_to_queue();
h.add_to_queue();
return 0;
}

When I create a Foo object inside Holder::add_to_queue(), that's a
temporary variable. And then when I add it to the queue, isn't that
bad? Or does the push create a new copy of the Foo object and stick
that inside the queue?

One of the requirements of the standard containers is that elements
must be copy constructable because they do indeed make a copy. This is
the reason why you can't put a std::auto_ptr in such containers (since
std::auto_ptrs have destructive copy semantics).
(wondering if I should use pointers or references instead of objects)

You can use pointers in containers, but you'll either need to use a
smart pointer that supports copy construction (e.g.
std::tr1::shared_ptr, aka boost::shared_ptr) or delete the items
yourself -- the container will deallocate the space used for a raw
pointer that it holds but not the pointee of that pointer.

Cheers! --M
 
J

Jakob Bieling

Joe Van Dyk said:
#include <queue>
#include <string>
#include <iostream>

using namespace std;

class Foo
{
public:
string data;
};

class Holder
{
public:
void add_to_queue()
{
Foo f;
f.data = "Sup!";
holder.push(f); // Bad?
}
queue<Foo> holder;
};

int main()
{
Holder h;
h.add_to_queue();
h.add_to_queue();
return 0;
}

When I create a Foo object inside Holder::add_to_queue(), that's a
temporary variable. And then when I add it to the queue, isn't that
bad? Or does the push create a new copy of the Foo object and stick
that inside the queue?

The latter. Your code is fine the way it is.
(wondering if I should use pointers or references instead of objects)

If your actual code is very similar to the example code above, I see
no reason for using pointers or references. When passing a Holder or a
Foo object around, you might want to do that by const-reference (this is
how you pass the temporary Foo to queue<Foo>::push, for example).

hth
 
J

Joe Van Dyk

Jakob said:
The latter. Your code is fine the way it is.




If your actual code is very similar to the example code above, I see
no reason for using pointers or references. When passing a Holder or a
Foo object around, you might want to do that by const-reference (this is
how you pass the temporary Foo to queue<Foo>::push, for example).

hth

Thanks.

In actuality, Holder::add_to_queue takes a string and creates a Foo
object based on that string. Then that Foo object gets pushed into the
queue.

Let's rename Foo to BaseMessage.

So, I have several classes that inherit from BaseMessage. So,
JoesMessage, JimsMessage, etc. The contents of the String that gets
passed to Holder::add_to_queue needs to be examined somehow and the
appropriate object needs to be constructed and inserted into the Queue
(ideas welcome on an elegant way to do that).

In that case, the queue would need to contain pointers to BaseMessage
objects, right? As there would be JoesMessages, JimMessages, etc all in
the same queue.
 
J

Jakob Bieling

Joe Van Dyk said:
Jakob Bieling wrote:
In actuality, Holder::add_to_queue takes a string and creates a Foo
object based on that string. Then that Foo object gets pushed into
the queue.

Let's rename Foo to BaseMessage.

So, I have several classes that inherit from BaseMessage. So,
JoesMessage, JimsMessage, etc. The contents of the String that gets
passed to Holder::add_to_queue needs to be examined somehow and the
appropriate object needs to be constructed and inserted into the Queue
(ideas welcome on an elegant way to do that).


If you must use strings to determine which object to construct, I
guess the method you outlined (parse string and construct based on
parse-result) is ok.

Reminds me of a script parser, where you have a script-type-name as
a string and need to construct a different object (representing the
type) depending on the string. In that case, I would do as you said.
In that case, the queue would need to contain pointers to BaseMessage
objects, right? As there would be JoesMessages, JimMessages, etc all
in the same queue.

Right, you can only work with pointers here. Note that the queue
will not delete the memory the pointers point to. It will only manage
the memory needed to store the pointers themselves.

hth
 
J

Joe Van Dyk

Jakob said:
If you must use strings to determine which object to construct, I
guess the method you outlined (parse string and construct based on
parse-result) is ok.

It's an XML string, joy!
Reminds me of a script parser, where you have a script-type-name as
a string and need to construct a different object (representing the
type) depending on the string. In that case, I would do as you said.




Right, you can only work with pointers here. Note that the queue
will not delete the memory the pointers point to. It will only manage
the memory needed to store the pointers themselves.

Is there a good idiom for popping a pointer to an element from the
queue, looking at the element, and then deleting the element?

Joe
 
J

Jakob Bieling

Joe Van Dyk said:
Jakob Bieling wrote:
[..] the queue would need to contain pointers to
BaseMessage objects, right? As there would be JoesMessages,
JimMessages, etc all in the same queue.
Right, you can only work with pointers here. Note that the queue
will not delete the memory the pointers point to. It will only manage
the memory needed to store the pointers themselves.

Is there a good idiom for popping a pointer to an element from the
queue, looking at the element, and then deleting the element?

I do not understand what you mean. Why not use 'queue<T>::front' to
get the top element, 'queue<T>::pop' to remove it from the queue and
then delete it (through the pointer you just got from 'front'):

regards
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

STL set Problem 5
Modify STL multiset 2
Newbie question 4
template issue 7
Question regarding copy constructor 22
A question on explicit copy constructors 4
STL stable_sort sorting issue 12
template 6

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,271
Latest member
BuyAtenaLabsCBD

Latest Threads

Top