Return a container from a class method

P

padulg

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?
 
M

mlimber

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
 
P

padul

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
 
P

peter koch

mlimber skrev:
(e-mail address removed) 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
 
P

padul

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

peter said:
mlimber skrev:
(e-mail address removed) 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
 
V

Victor Bazarov

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

peter said:
mlimber skrev:
(e-mail address removed) 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
 
M

mlimber

padul said:
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
 
M

mlimber

peter said:
mlimber skrev:

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
 
P

peter koch

mlimber skrev:
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 said:
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
 
M

mlimber

peter said:
mlimber skrev:

It is NEVER premature pessimization if the result requires you to write
obfuscated code such as
container <t> c;
cfunc(c);
instead of


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).
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
 
J

Jerry Coffin

[ ... ]
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...
 

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

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top