Return a container from a class method

Discussion in 'C++' started by padulg@gmail.com, Jul 27, 2006.

  1. Guest

    Hello at all,
    I have a problem: I have a class named "ball" with a method named
    "split".

    This is the declaration in ball.h:

    class ball : public procObject
    {
    public:
    ball();
    ball(GLfloat size, GLfloat x_pos, GLfloat y_pos, GLfloat z_pos);
    ~ball();

    GLvoid draw(GLint mode); //implemented
    ball* clone();

    list<ball*> split(GLint ntimes);
    };

    This is th implementation in ball.cpp

    list<ball*> ball::split(GLint ntimes)
    {
    list<ball*> new_balls;
    .....
    ....

    return new_balls;

    }

    Is it possible, and if it is how can I do that?
     
    , Jul 27, 2006
    #1
    1. Advertising

  2. mlimber Guest

    wrote:
    > Hello at all,
    > I have a problem: I have a class named "ball" with a method named
    > "split".
    >
    > This is the declaration in ball.h:
    >
    > class ball : public procObject
    > {
    > public:
    > ball();
    > ball(GLfloat size, GLfloat x_pos, GLfloat y_pos, GLfloat z_pos);
    > ~ball();
    >
    > GLvoid draw(GLint mode); //implemented
    > ball* clone();
    >
    > list<ball*> split(GLint ntimes);
    > };
    >
    > This is th implementation in ball.cpp
    >
    > list<ball*> ball::split(GLint ntimes)
    > {
    > list<ball*> new_balls;
    > ....
    > ...
    >
    > return new_balls;
    >
    > }
    >
    > Is it possible, and if it is how can I do that?


    If you're lucky, the compiler might optimize the copy of the list away,
    but generally speaking it can't do so. A better way would be to pass
    the list in as a reference:

    void ball::split( GLint ntimes, list<ball*>& new_balls )
    {
    list.clear();
    // ... same stuff as before, except for the return
    }

    Cheers! --M
     
    mlimber, Jul 27, 2006
    #2
    1. Advertising

  3. padul Guest

    The compiler return ,me these errors:

    ball.h:23: error: 'list' has not been declared
    ball.h:23: error: expected ',' or '...' before '<' to


    is there anyway to resolve this problem, I would know how to pass as
    parameter a container o return a container from a method of a class.
    Thanks.


    Padul

    mlimber wrote:
    > wrote:
    > > Hello at all,
    > > I have a problem: I have a class named "ball" with a method named
    > > "split".
    > >
    > > This is the declaration in ball.h:
    > >
    > > class ball : public procObject
    > > {
    > > public:
    > > ball();
    > > ball(GLfloat size, GLfloat x_pos, GLfloat y_pos, GLfloat z_pos);
    > > ~ball();
    > >
    > > GLvoid draw(GLint mode); //implemented
    > > ball* clone();
    > >
    > > list<ball*> split(GLint ntimes);
    > > };
    > >
    > > This is th implementation in ball.cpp
    > >
    > > list<ball*> ball::split(GLint ntimes)
    > > {
    > > list<ball*> new_balls;
    > > ....
    > > ...
    > >
    > > return new_balls;
    > >
    > > }
    > >
    > > Is it possible, and if it is how can I do that?

    >
    > If you're lucky, the compiler might optimize the copy of the list away,
    > but generally speaking it can't do so. A better way would be to pass
    > the list in as a reference:
    >
    > void ball::split( GLint ntimes, list<ball*>& new_balls )
    > {
    > list.clear();
    > // ... same stuff as before, except for the return
    > }
    >
    > Cheers! --M
     
    padul, Jul 27, 2006
    #3
  4. peter koch Guest

    mlimber skrev:

    > wrote:

    [snip]
    > >
    > > This is th implementation in ball.cpp
    > >
    > > list<ball*> ball::split(GLint ntimes)
    > > {
    > > list<ball*> new_balls;
    > > ....
    > > ...
    > >
    > > return new_balls;
    > >
    > > }
    > >
    > > Is it possible, and if it is how can I do that?

    >
    > If you're lucky, the compiler might optimize the copy of the list away,
    > but generally speaking it can't do so. A better way would be to pass
    > the list in as a reference:
    >
    > void ball::split( GLint ntimes, list<ball*>& new_balls )
    > {
    > list.clear();
    > // ... same stuff as before, except for the return
    > }
    >


    I have two questions: first why you choose to force a weird syntax
    because some optimization not would take place. Is there any indication
    that the procedure in question is on an expensive path?
    My second question is why you believe the optimizer can't do the RVO.
    The compilers I use all perform RVO without any problems provided
    optimizations are turned on. In that case your code is not only more
    verbose and less natural - it is also slower.

    > Cheers! --M


    Recheers
    Peter
     
    peter koch, Jul 27, 2006
    #4
  5. padul Guest

    I'm working under linux enviroment with kdevelop3 that use g++.
    There is any solution at my question?
    Thanks

    peter koch wrote:
    > mlimber skrev:
    >
    > > wrote:

    > [snip]
    > > >
    > > > This is th implementation in ball.cpp
    > > >
    > > > list<ball*> ball::split(GLint ntimes)
    > > > {
    > > > list<ball*> new_balls;
    > > > ....
    > > > ...
    > > >
    > > > return new_balls;
    > > >
    > > > }
    > > >
    > > > Is it possible, and if it is how can I do that?

    > >
    > > If you're lucky, the compiler might optimize the copy of the list away,
    > > but generally speaking it can't do so. A better way would be to pass
    > > the list in as a reference:
    > >
    > > void ball::split( GLint ntimes, list<ball*>& new_balls )
    > > {
    > > list.clear();
    > > // ... same stuff as before, except for the return
    > > }
    > >

    >
    > I have two questions: first why you choose to force a weird syntax
    > because some optimization not would take place. Is there any indication
    > that the procedure in question is on an expensive path?
    > My second question is why you believe the optimizer can't do the RVO.
    > The compilers I use all perform RVO without any problems provided
    > optimizations are turned on. In that case your code is not only more
    > verbose and less natural - it is also slower.
    >
    > > Cheers! --M

    >
    > Recheers
    > Peter
     
    padul, Jul 27, 2006
    #5
  6. "padul" <> wrote...
    > I'm working under linux enviroment with kdevelop3 that use g++.
    > There is any solution at my question?
    > Thanks
    >
    > peter koch wrote:
    >> mlimber skrev:
    >>
    >> > wrote:

    >> [snip]
    >> > >
    >> > > This is th implementation in ball.cpp
    >> > >
    >> > > list<ball*> ball::split(GLint ntimes)
    >> > > {
    >> > > list<ball*> new_balls;
    >> > > ....
    >> > > ...
    >> > >
    >> > > return new_balls;
    >> > >
    >> > > }
    >> > >
    >> > > Is it possible, and if it is how can I do that?


    Why ask if it's possible? Why not just try it? The only negative
    side I see is that you keep pointers. Make sure you don't try storing
    pointers to local objects in your 'list'.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Jul 27, 2006
    #6
  7. mlimber Guest

    padul wrote:
    > mlimber wrote:
    > > void ball::split( GLint ntimes, list<ball*>& new_balls )
    > > {
    > > list.clear();
    > > // ... same stuff as before, except for the return
    > > }

    >
    > The compiler return ,me these errors:
    >
    > ball.h:23: error: 'list' has not been declared
    > ball.h:23: error: expected ',' or '...' before '<' to
    >
    >
    > is there anyway to resolve this problem, I would know how to pass as
    > parameter a container o return a container from a method of a class.


    First, put your reply to other posts inline or below the post you are
    responding to. I've fixed your reply above.

    Second, change list.clear() to new_balls.clear(). Mea culpa.

    Cheers! --M
     
    mlimber, Jul 27, 2006
    #7
  8. mlimber Guest

    peter koch wrote:
    > mlimber skrev:
    > > If you're lucky, the compiler might optimize the copy of the list away,
    > > but generally speaking it can't do so. A better way would be to pass
    > > the list in as a reference:
    > >
    > > void ball::split( GLint ntimes, list<ball*>& new_balls )
    > > {
    > > list.clear();
    > > // ... same stuff as before, except for the return
    > > }
    > >

    >
    > I have two questions: first why you choose to force a weird syntax
    > because some optimization not would take place. Is there any indication
    > that the procedure in question is on an expensive path?


    It could be premature optimization, sure. But let's also not
    prematurely pessimize.

    > My second question is why you believe the optimizer can't do the RVO.
    > The compilers I use all perform RVO without any problems provided
    > optimizations are turned on. In that case your code is not only more
    > verbose and less natural - it is also slower.


    First, the OP didn't specify the compiler in question. Some don't do
    the RVO at all. Second, RVO can only be applied on initialization. For
    instance...

    vector<int> Foo()
    {
    vector<int> v;
    v.push_back( 1 );
    v.push_back( 2 );
    return v;
    }

    void Bar()
    {
    vector<int> v = Foo(); // RVO applied!
    // ... use v somehow ...
    v = Foo(); // RVO not applied!
    }

    For more info, see this section from _Efficient C++ Programming_ by
    Lippman:

    http://www.awprofessional.com/articles/printerfriendly.asp?p=25033&rl=1

    Cheers! --M
     
    mlimber, Jul 27, 2006
    #8
  9. peter koch Guest

    mlimber skrev:

    > peter koch wrote:
    > > mlimber skrev:
    > > > If you're lucky, the compiler might optimize the copy of the list away,
    > > > but generally speaking it can't do so. A better way would be to pass
    > > > the list in as a reference:
    > > >
    > > > void ball::split( GLint ntimes, list<ball*>& new_balls )
    > > > {
    > > > list.clear();
    > > > // ... same stuff as before, except for the return
    > > > }
    > > >

    > >
    > > I have two questions: first why you choose to force a weird syntax
    > > because some optimization not would take place. Is there any indication
    > > that the procedure in question is on an expensive path?

    >
    > It could be premature optimization, sure. But let's also not
    > prematurely pessimize.


    It is NEVER premature pessimization if the result requires you to write
    obfuscated code such as
    container <t> c;
    cfunc(c);
    instead of
    container <t> c = cfunc();
    >
    > > My second question is why you believe the optimizer can't do the RVO.
    > > The compilers I use all perform RVO without any problems provided
    > > optimizations are turned on. In that case your code is not only more
    > > verbose and less natural - it is also slower.

    >
    > First, the OP didn't specify the compiler in question. Some don't do
    > the RVO at all. Second, RVO can only be applied on initialization. For
    > instance...


    Just out of curiosity. What compiler released in this millenium does
    not do RVO or NRVO?
    >
    > vector<int> Foo()
    > {
    > vector<int> v;
    > v.push_back( 1 );
    > v.push_back( 2 );
    > return v;
    > }
    >
    > void Bar()
    > {
    > vector<int> v = Foo(); // RVO applied!
    > // ... use v somehow ...
    > v = Foo(); // RVO not applied!
    > }


    Right - but the first solution is still preferable. First, you keep the
    natural look of the code (which is most important - code is written to
    be read!). Second, you can more easily get the strong exception
    guarantee here and lastly this code will be as efficient as your
    "return value in a parameter" as soon as the new r-value extensions get
    implemented ;-)

    /Peter

    >
    > For more info, see this section from _Efficient C++ Programming_ by
    > Lippman:
    >
    > http://www.awprofessional.com/articles/printerfriendly.asp?p=25033&rl=1
    >


    An excellent book no longer in my possession ;.-)
    > Cheers! --M


    /Peter
     
    peter koch, Jul 27, 2006
    #9
  10. mlimber Guest

    peter koch wrote:
    > mlimber skrev:
    > > peter koch wrote:
    > > > mlimber skrev:
    > > > > If you're lucky, the compiler might optimize the copy of the list away,
    > > > > but generally speaking it can't do so. A better way would be to pass
    > > > > the list in as a reference:
    > > > >
    > > > > void ball::split( GLint ntimes, list<ball*>& new_balls )
    > > > > {
    > > > > list.clear();
    > > > > // ... same stuff as before, except for the return
    > > > > }
    > > > >
    > > >
    > > > I have two questions: first why you choose to force a weird syntax
    > > > because some optimization not would take place. Is there any indication
    > > > that the procedure in question is on an expensive path?

    > >
    > > It could be premature optimization, sure. But let's also not
    > > prematurely pessimize.

    >
    > It is NEVER premature pessimization if the result requires you to write
    > obfuscated code such as
    > container <t> c;
    > cfunc(c);
    > instead of
    > container <t> c = cfunc();
    >
    > > First, the OP didn't specify the compiler in question. Some don't do
    > > the RVO at all. Second, RVO can only be applied on initialization. For
    > > instance...

    >
    > Just out of curiosity. What compiler released in this millenium does
    > not do RVO or NRVO?


    Well, like I said, the OP didn't specify, and unfortunately, not
    everyone has the option of use modern compilers. (Half of my current
    project uses VC6, for instance, while the other half uses a quite
    compliant EDG-based compiler, and some code has to work on both).

    > >
    > > vector<int> Foo()
    > > {
    > > vector<int> v;
    > > v.push_back( 1 );
    > > v.push_back( 2 );
    > > return v;
    > > }
    > >
    > > void Bar()
    > > {
    > > vector<int> v = Foo(); // RVO applied!
    > > // ... use v somehow ...
    > > v = Foo(); // RVO not applied!
    > > }

    >
    > Right - but the first solution is still preferable. First, you keep the
    > natural look of the code (which is most important - code is written to
    > be read!). Second, you can more easily get the strong exception
    > guarantee here and lastly this code will be as efficient as your
    > "return value in a parameter" as soon as the new r-value extensions get
    > implemented ;-)


    Certainly this is the preferable syntax, but it, too, has a drawback
    besides the question of compiler support: it requires the programmer to
    remember to make use of RVO and not perform an implicit copy. I see it
    as a trade-off, which can be decided one way or the other in specific
    instances by the needs of the project, but if a conservative approach
    should be taken, then the explicit parameter approach should be used.

    Cheers! --M
     
    mlimber, Jul 28, 2006
    #10
  11. Jerry Coffin Guest

    In article <>,
    says...

    [ ... ]

    > list<ball*> ball::split(GLint ntimes)
    > {
    > list<ball*> new_balls;
    > ....
    > ...
    >
    > return new_balls;
    >
    > }
    >
    > Is it possible, and if it is how can I do that?


    This is entirely possible, but depending on your compiler, _may_ be
    quite expensive. My own advice would be: instead of dealing with a
    container as a whole, have the callee pass an output iterator, and
    put the data wherever it points to:

    template <class OutIt>
    ball::split(GLint ntimes, OutIt &output) {
    for (int i=0; i<ntimes; i++)
    *output++ = whatever;
    }

    Just for one example, this allows split to be relatively independent
    of the type of container where its output gets put. If (for example)
    you find that the overhead of a list is excessive and decide to use a
    deque instead, you can do that without changing its code at all.
    Likewise, during debugging you might decide to feed its output
    directly to an ostream_iterator -- and (again) it won't mind in the
    least. In fact, you can perfectly reasonably have some debugging code
    that feeds the output directly to a stream, while other code feeds it
    to a vector, and still other code feeds it to a list...

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Jul 28, 2006
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Vivi Orunitia
    Replies:
    11
    Views:
    4,481
    Martijn Lievaart
    Feb 4, 2004
  2. Maitre Bart
    Replies:
    2
    Views:
    527
    Maitre Bart
    Feb 11, 2004
  3. Steven T. Hatton
    Replies:
    4
    Views:
    3,909
    Rob Williscroft
    Dec 5, 2004
  4. Replies:
    4
    Views:
    805
    Daniel T.
    Feb 16, 2006
  5. Xeno Campanoli
    Replies:
    0
    Views:
    231
    Xeno Campanoli
    Feb 13, 2006
Loading...

Share This Page