Silly STL question...

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Joe Van Dyk

    Silly STL question...

    #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
  • mlimber

    #2
    Re: Silly STL question...

    Joe Van Dyk wrote:[color=blue]
    > #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?[/color]

    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).
    [color=blue]
    > (wondering if I should use pointers or references instead of objects)[/color]

    You can use pointers in containers, but you'll either need to use a
    smart pointer that supports copy construction (e.g.
    std::tr1::share d_ptr, aka boost::shared_p tr) 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

    Comment

    • Jakob Bieling

      #3
      Re: Silly STL question...

      Joe Van Dyk <joe.vandyk@boe ing.com> wrote:[color=blue]
      > #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?[/color]

      The latter. Your code is fine the way it is.
      [color=blue]
      > (wondering if I should use pointers or references instead of objects)[/color]

      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>::pus h, for example).

      hth
      --
      jb

      (reply address in rot13, unscramble first)


      Comment

      • Joe Van Dyk

        #4
        Re: Silly STL question...

        Jakob Bieling wrote:[color=blue]
        > Joe Van Dyk <joe.vandyk@boe ing.com> wrote:
        >[color=green]
        >>#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?[/color]
        >
        >
        > The latter. Your code is fine the way it is.
        >
        >[color=green]
        >>(wondering if I should use pointers or references instead of objects)[/color]
        >
        >
        > 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>::pus h, for example).
        >
        > hth[/color]

        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.

        Comment

        • Jakob Bieling

          #5
          Re: Silly STL question...

          Joe Van Dyk <joe.vandyk@boe ing.com> wrote:
          [color=blue]
          > Jakob Bieling wrote:[/color]
          [color=blue][color=green]
          >> Joe Van Dyk <joe.vandyk@boe ing.com> wrote:[/color][/color]
          [color=blue][color=green][color=darkred]
          >>> #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;
          >>> }[/color][/color][/color]

          [color=blue][color=green]
          >> 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>::pus h, for example).[/color][/color]
          [color=blue]
          > 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).[/color]


          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.
          [color=blue]
          > 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.[/color]

          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
          --
          jb

          (reply address in rot13, unscramble first)


          Comment

          • Joe Van Dyk

            #6
            Re: Silly STL question...

            Jakob Bieling wrote:[color=blue]
            > Joe Van Dyk <joe.vandyk@boe ing.com> wrote:
            >
            >[color=green]
            >>Jakob Bieling wrote:[/color]
            >
            >[color=green][color=darkred]
            >>>Joe Van Dyk <joe.vandyk@boe ing.com> wrote:[/color][/color]
            >
            >[color=green][color=darkred]
            >>>>#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;
            >>>>}[/color][/color]
            >
            >
            >[color=green][color=darkred]
            >>> 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).[/color][/color]
            >
            >[color=green]
            >>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).[/color]
            >
            >
            >
            > 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.[/color]

            It's an XML string, joy!
            [color=blue]
            >
            > 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.
            >
            >[color=green]
            >>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.[/color]
            >
            >
            > 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.[/color]

            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

            Comment

            • Jakob Bieling

              #7
              Re: Silly STL question...

              Joe Van Dyk <joe.vandyk@boe ing.com> wrote:
              [color=blue]
              > Jakob Bieling wrote:[/color]
              [color=blue][color=green]
              >> Joe Van Dyk <joe.vandyk@boe ing.com> wrote:[/color][/color]
              [color=blue][color=green][color=darkred]
              >>> [..] the queue would need to contain pointers to
              >>> BaseMessage objects, right? As there would be JoesMessages,
              >>> JimMessages, etc all in the same queue.[/color][/color][/color]
              [color=blue][color=green]
              >> 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.[/color][/color]

              [color=blue]
              > Is there a good idiom for popping a pointer to an element from the
              > queue, looking at the element, and then deleting the element?[/color]

              I do not understand what you mean. Why not use 'queue<T>::fron t' 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
              --
              jb

              (reply address in rot13, unscramble first)


              Comment

              Working...