How to pass STL containers (say a vector) ?

P

peter koch

Markus Schoder skrev:
Unfortunately this does not work for assigning to an already existing
vector.
You can still benefit from RVO by first creating a new vector
and then swapping it into the existing one but that is all but
intuitive and only works for fast swappable objects.

I agree that assigning to already constructed objects is non-optimal
and that you have to use somewhat unintuitive code for optimal
performance in that case. But my guess is that this situation occurs
rarely. And the other solution is counterintuitive in all cases.
You can also just do result.clear() and use it directly.
In the example above you most likely could. But in the general case you
would reduce the exception-guarantee for no benefit at all.
Because of what I said above I still think this approach has some value
even though it is more clumsy to use.
My opinion is that readability should be the number one priority in the
general case. So I'd just have to differ.

/Peter
 
P

peter koch

Daniel T. skrev:
peter koch said:
Daniel T. skrev:


True. So we agree here ;-)


It is a pretty common method of returning multiple datum to the caller.



True. Your point?
My point is that there is a difference between having a container and a
pair of iterators. Sometimes a pair of iterators just can't do the job.
Odd, in your code above, "normalise_container" returns void yet you are
passing its return to print? There is obviously a debate about whether
such a return is efficient.
Obviously, normalise_container should have returned a vector. I presume
you could guess that just as I did guess the meaning of your
"tempalted" function declaration ;-)
I will happily admit that templating to the container rather than two
iterators is a great idea, but templating to two iterators is more
idiomatic...
I do not intend to template anything at all. If you read the original
post, you'll understand why. The advice was given to a newcomer to C++
and in situations like that. you should avoid recommending templates
just as you should avoid iterators which do complicate things quite a
lot.

/Peter
 
D

Daniel T.

"peter koch said:
Daniel T. skrev:
peter koch said:
Daniel T. skrev:

Daniel T. skrev:

[snip]
I beg to differ, std::copy does return a container in its own way...
Well... I just notice the line above. I agree that std::copy might make
the data copied available somehow. The difference is one of words. I
meant return as used in a C++ program whereas you seemingly mean return
in the sense that the data will afterwards be available to the caller.

True. So we agree here ;-)
vector<int> foo;
copy( istream_iterator<int>( cin ), istream_iterator<int>(),
back_inserter( foo ) );

The data in foo was returned...

So you mean that the data was returned in foo? In that case we simply
have a different perception of "returning values". To me, std::copy
does not return data in foo.

What about transform?

Perhaps this example better demonstrates what i mean?
vector<int> foo;
foo.push_back(117);
copy( istream_iterator<int>( cin ), istream_iterator<int>(),
back_inserter( foo ) );

copy definitely does not return its data in foo.

How so? All the data collected inside the copy function is given to the
caller through foo...

Surely. But std::copy did not return the data - it simply put them into
some iterator.

It is a pretty common method of returning multiple datum to the caller.

In other words when you want to pass in a container:

tempalte < typename InIt >
void func( InIt first, InIt last );

Fine! And now let func remove the second element.

The same way std::remove does it.
That does not remove the data from the container.

True. Your point?
My point is that there is a difference between having a container and a
pair of iterators. Sometimes a pair of iterators just can't do the job.
Odd, in your code above, "normalise_container" returns void yet you are
passing its return to print? There is obviously a debate about whether
such a return is efficient.
Obviously, normalise_container should have returned a vector. I presume
you could guess that just as I did guess the meaning of your
"tempalted" function declaration ;-)

Yes, I assumed as much. Hence the comment about the debate. There are no
efficiency concerns about the use of iterators in this context.

I do not intend to template anything at all. If you read the original
post, you'll understand why. The advice was given to a newcomer to C++
and in situations like that. you should avoid recommending templates
just as you should avoid iterators which do complicate things quite a
lot.

I realize that the OP is somewhat new to C++, that is why I recommended
he use idiomatic code. The standard way of passing containers to and
from functions (ie the way the *standard* passes containers to and from
functions) is through the use of iterators.

I think it is wrong to avoid iterators when working with beginners,
better iterators than bald pointers IMO. I also think it is wrong to
avoid templates in simple code like this (though I don't expect new
people to understand using them in Policy-Based Design situations.) If
however, I did want to avoid templates, I would still recommend iterator
based container passing. That way, at least the calling code will look
idiomatic.

We have a difference of opinion. I'll teach my way, you will teach your
way. When my students first come across code using the standard
algorithms they will think nothing of it.
 
P

peter koch

Daniel T. skrev:
[snip]
I think it is wrong to avoid iterators when working with beginners,
better iterators than bald pointers IMO. I also think it is wrong to
avoid templates in simple code like this (though I don't expect new
people to understand using them in Policy-Based Design situations.) If
however, I did want to avoid templates, I would still recommend iterator
based container passing. That way, at least the calling code will look
idiomatic.

I do not object to using iterators as such; rather I find it is better
to avoid these as the traps are many - e.g.
std::vector<...> v;
func(v.begin());

If the problem is to return a STL-container I thus still believe the
correct answer is to return it as you'd return an int - and NOT pass an
iterator to the container to avoid the expensive copy - oh but remember
to use an back_inserter and not just your plain begin() and end() ...
and also be sure that the container is empty so that you will return
the result properly and not append the result to whatever happens to be
in the container already. But watch out if your function could fail -
there might be some exception guarantees that you can now no longer
provide so perhaps you should create a temporary container and do a
swap after the call succeeds.
This level of detail is just plain wrong unless you are absolutely
confident that performance is going to suffer and that performance is
important.
We have a difference of opinion. I'll teach my way, you will teach your
way. When my students first come across code using the standard
algorithms they will think nothing of it.

I do not teach, but would surely advice any student of mine to use
<algorithm> whenever feasible.

/Peter
 

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
474,007
Messages
2,570,266
Members
46,865
Latest member
AveryHamme

Latest Threads

Top