While working in a project with some legacy code i found this function:
std::vector<std::string> Object::getTypes(){
static std::string types [] = {"type1","type2", "type3"};
return std::vector<std::string> (types , types +2);
}
I would probably have written this as:
std::vector<std::string> Object::getTypes(){
std::vector<std::string> types;
types.push_back("type1");
types.push_back("type2");
types.push_back("type3");
return types;
}
Is this merely a style choice or is there something I'm missing? Any help would be greatly appreciated. Sorry if this is too basic.
Update:
Actually found different classes that override the same method do it one way or the other, so It's even more ambiguous. I would make them all the same but would prefer the better approach, if there is one.
Edit
Please note that the above legacy code is incorrect because it initializes the vector with only the first two elements of the array. However, this error has been discussed in the comments and thus should be preserved.
The correct initialization should have read as follows:
...
return std::vector<std::string> (types, types + 3);
...
If you have a C++11 capable compiler and library, returning an initializer list should be enough:
std::vector<std::string> Object::getTypes(){
return {"type1","type2", "type3"};
}
The code you found is more efficient (because types[] is only allocated once and push_back can/will cause re-allocations). The difference though is marginal, and unless you call getTypes in a (relatively big) loop it shouldn't matter at all (and probably it won't matter much even when you do call it in a big loop).
As such, unless it creates a concrete performance problem, it's a style choice.
Basically it's a style choice. I'd probably do something more like
std::vector<std::string> Object::getTypes(){
static std::string types [] = {"type1","type2", "type3"};
return std::vector<std::string> (types,
types + (sizeof(types)/sizeof(std::string)) );
}
which lets you change the number of things in types, without having to remember to update the count in the next line.
The array types in the first example is declared static. This means it only exists once in memory. So there are three options for what to return and they live in static memory. Then, when you create the vector to return, you are able to allocate it's memory in one shot by passing the beginning and ending of the array as iterators.
By doing it this way, you don't have successive calls to push_back which means the vector won't have to reallocate its internal block of memory.
Also, when the vector is constructed as part of the return call, older compilers will have an easier time of doing return value optimization.
One reason I like to use this style of initialization with iterators (and C++11's uniform initialization and initializer lists) is that it helps separating data from code.
Repeating push_back a lot of times feels bad because I desperately need to refactor that. Also, when you really just need to initialize the container with data, then you want to see a list of the data, and not really code that generates data. The method you found in the original version matches that principle better.
Related
I'm introducing myself to C++, and sadly it's starting to seem like the support for dynamically created arrays of fixed size (but with the size known only at run time) is very poor in C++, as new[] can't call an arbitrary user-specified constructor with user-set arguments.
Consider class A which has a number of constructors, each with some parameters. Assume that a constructor without parameters would be useless (I don't want to have to write one if I essentially don't need it). I guess the following doesn't matter, but, just in case: assume that A contains only a possibly large std::vector<Internal> (Internal is a private class, T and S parameterize A) and an integer counter as far as data members go. Also, A is parameterized.
Assume we want n instances of A stored contiguously in memory as an array, where n is determined at run time and constant afterwards. We want to be able create and initialize the structure with a single call that passes arguments to a constructor of A, or something similar. So each instance in the array gets the same, but programmatic initialization. EDIT: sorry, I didn't mean to say I want O(1) initialization, as that's impossible, I just wanted O(n) initialization, but so that I can create the array in one statement. I.e., so that I don't have to write an initialization loop for every array I create.
A possible, but suboptimal, solution is std::vector<A<T,S>>, but assume we can't live with the inefficiency. (Remember that std::vector supports resizing.)
How to implement and/or use an efficient solution with a nice API?
I would prefer a solution that doesn't reimplement half of the standard library, i.e. consider C++20 features and the standard library available for the implementation. Also, don't make me violate the C++ aliasing rules.
A possibly related question is why is such a "fixed_size_vector" class missing from the standard library?
(BTW: not that it matters, but please don't say "just use vector", because in this case I'm indeed going to go with the mentioned suboptimal solution, as the performance is not significant for my toy program, but in the real world the performance will matter one day and I want to be prepared. EDIT: I did not mean I want to optimize my toy program, rather I was referring to the fact that one day I will have to optimize some other program.)
EDIT: answering to some commenters: wrapping std::vector could provide the right abstraction, but it would be unnecessarily inefficient. A comment linked a question whose top answer explains this nicely:
dynarray is smaller and simpler than vector, because it doesn't need
to manage separate size and capacity values, and it doesn't need to
store an allocator
(dynarray here was a proposed addition to stdlib that seems to be what I wanted, except that it was also supposed to rely on special compiler support for some of its semantics). Of course, this difference compared to std::vector won't matter most of the time, but it would still be good if I was able to simply use the right tool for the job.
There is a proposal to add a fixed capacity vector to the standard.
Note that this proposal proposes the capacity be known at compile-time, so it's not applicable in your case.
There are also some open source libraries that implement one, e.g., Boost's static_vector, or . If you really want a fixed-capacity vector, you can use one of the open source implementations that exist out there.
If you really know what you're doing, you could write one on your own, but that's not the case for >99% of C++ users.
However, it should be noted that reserve()ing space on a vector will probably have the effect you want, and there's probably no need for an actual fixed capacity vector.
Since you mention that the size is only known at runtime this is exactly what std::vector is meant to be used for.
template <typename T, typename...Args>
auto make_vector(std::size_t size, const Args&...args) -> std::vector<T>
{
auto result = std::vector<T>{};
result.reserve(size); // whatever the known size is
for (auto i = 0; i < size; ++i) {
result.emplace_back(args...);
}
return result;
}
// Use like:
auto vec = make_vector<std::string>(20, "hello world");
This will pre-allocate enough room for size entries of type T, and the loop will call T's constructor with whatever arguments you pass it.
Be aware that:
No additional constructors are called.
No extra memory is used.
No copies or relocations are performed.
The returned vector is not copied (or even moved) with c++17 or above thanks to guaranteed copy elision.
Doing this is as optimal as you can get whether you use a specialized container or otherwise. This is why every experienced C++ developer will tell you the same thing: std::vector is the solution.[2]
Note: The above function uses const Args&... for propagation and not proper forwarding references, since rvalue references could result in use-after-move bugs.[1]
A specialized container like a fixed_size_vector that you mention will either be one of two things:
Fixed at compile-time on the max size, in which case it wouldn't work for you since you mentioned the size is only known at runtime
Fixed at runtime on the max size, in which case it will do exactly what I suggested above, since it will reserve the storage space up-front.
It is not possible at the language level to dynamically construct N objects only known at runtime using a custom constructor. Full stop. This could be done if the sequence is known at compile-time, but not runtime.
C++ is statically compiled, so we cannot variadically expand a runtime n value into a pack of T{...} constructor calls; it's simply not possible. This means there will be a loop every time. Thus the most optimal thing you can do is allocate n objects once, and call T's constructor n times.
[1] A short-hand syntax for passing a list of arguments to all of a sequences constructors is not a good general solution in C++. In fact, it would be suboptional. This would either force copies via const lvalue references, or it would allow for rvalues -- in which case only the first object constructed will get a valid value, and everything after will receive a use-after-moved object! Just imagine unique_ptr to a sequence of T's. Only the first instance will get a valid pointer, and everything else will receive nullptr
[2] Honestly, about the only real optimization you might be able to make on this solution would be to use a custom allocator, such as a std::pmr::vector with a stack-allocated memory buffer resource.
Footnote
I strongly advise you to get over the "efficiency first" mentality. Most developers' intuition on what is and is not efficient is wrong; this is why profilers are so important. Things like speculative execution, cache locality, and pipelining play a huge role in performance -- and these things are far more complex than simply constructing a dynamic array of objects.
Real software is written for other developers, not for the machine. It's better to have code that is maintainable and scalable, and optimized in places where bottlenecks have been identified through proper tooling.
I'm making a global struct of structures by declaring them on the header file file this:
const int Numberof=8;
struct FP
{
std::string callsign;
std::string de_airport;
std::string ar_airport;
std::string aircraft_type;
int trueairspeed;
std::vector<string> route;
std::vector<int> FL_route;
int current_state;
std::string current_WP;
std::string hour_lastWP;
std::string next_WP;
std::string hour_nextWP;
};
struct FP FP_list[Numberof];
Problem is, I defined the Numberof to 8 just to make it through my case. In the future that value is going to vary and i won't know its value until way later. What I'm interested in is a way of adding an instance to FP_list every time FP_listis called. Is there any way of doing it?
I know that making std::vector <FP> FP_listand then using vector::push_back is a solution, but since I don't know when and where my program ends I won't be able to swap my vector properly. Is that a problem, not calling .swap(Numberof)?
Edit: Oh and also, what I said about FP_list.swap(Numberof) applies to my objects of structure FP. Will it be a problem if I don't swap route and FL_route?
You can use std::vector<FP> FP_list and then using vector::push_back to add elements to it. Based on the structures given, there's no need to do swap anywhere (or even an option to do so).
swap is to swap the contents of two different vectors of the same type, which you don't have.
If you read somewhere that you should use swap after finishing using a vector, you may have misunderstood the scenario described. I can't come up with a scenario where it would be useful off the top of my head, but it does not relate to when the program finishes (if you consider that swap just swaps the content of 2 vectors, the other vector will still be left with the data, so whether it's in the one or the other, it doesn't really matter - it still needs to be freed).
For future reference, std::vector<FP> FP_list was the solution and in the function where I fill the structures, the solution to add one element do the vector each time I call the function is:
FP_List.push_bak(FP())
That's exactly what i was looking for
I have created this structure:
struct xlsmain {
vector<sub_parts> sb;
string name;
}
struct sub_parts {
vector<pio_parts> pio;
string name_pio;
string direction;
string partition;
}
struct pio_parts {
string pio_name;
vector<report_specs> report;
}
struct report_specs {
string name;
vector<string> value;
}
struct xlsmain* interface = new xlsmain[100];
The nesting is necessary because every element is related in a heirarchial manner. The problem I am facing right now is how to enter values in this structure.
EDIT: I don't like using push_back() because every time I'll have to declare a separate structure. So for instance if I want to add a sub part to xlsmain, I have to declare a variable:
sub_parts sb1;
Then I have to feed values into this structure until it is finished, when I can use:
interface[i].sb.push_back(sb1);
Further, if nesting is involved then a number of structures like sb1 will also have to be created. This leads to having to create a large number of variables just to enter even a single value in my structure.
An option would be to use a std::map instead of the vector, then you can do something like this
xmlsmain["some element"].sb["some other"].direction = "up";
In this way, elements "some element" and "some other" are automatically created.
Before the edit, your concern that push_back() was "too complex" wasn't clear. (It sounded like perhaps even you didn't like the name of the method...or something strange like that?)
I'll try to get to addressing the new issue raised. But I will reiterate that although you are using the standard library string and vector classes, your structures are not themselves getting the advantages of C++!
You don't have constructors, destructors, or methods. Those are the foundations of letting data objects "come alive" with "magic" behavior that lets clients of these classes write simpler, more abstract code. This is helpful even if your only "client" is just more of your own code!
Let's say before you had code like:
pio_parts pp;
pp.pio_name = "this string will be stored in the name";
pp.report.push_back(someReport);
pp.report.push_back(anotherReport);
If you add a constructor and a method to your structure, like this:
struct pio_parts {
string pio_name;
vector<report_specs> report;
pio_parts(string newName) {
pio_name = newName;
}
void addReport(report_specs newSpecs) {
report.push_back(newSpecs);
}
};
Then the code above gets nicer:
pio_parts pp ("this string will be stored in the name");
pp.addReport(someReport);
pp.addReport(anotherReport);
Though really, you've not done much than save yourself from having to know the name of the data member in pio_parts to add to. Now you remember a method name instead. You save a little typing, but push_back() was about as good.
HOWEVER if there were more related operations you need to do inside of addReport() than just add to the vector, you now have a place to put all that code. That way the user of your class can not worry about whatever bookkeeping is necessary to add a report...they just ask that it be done! Also, since there's no call to push_back() it's no longer necessary for whoever is calling addReport() to know that the list is being stored in a vector.
I've deliberately not even bothered to try and scratch deeper into the specifics of references, copy-construction, smart pointers, member initialization syntax, or even class vs struct. It's too deep a language. Take a time out ASAP and carefully read this short paper by Bjarne Stroustrup that lays out that clear contrast in methodology:
Learning Standard C++ as a New Language
Now I'll try to get on to your other concern. First of all, you do not have to create a named instance of a variable in C++ to pass it to a function. You can rewrite:
sub_parts sb1;
interface[i].sb.push_back(sb1);
...as instead:
interface[i].sb.push_back(sub_parts ());
Not particularly useful in this case, as the object is constructed empty...so you just pushed something useless. But if your constructor took parameters that filled the object, it would be fine. You can even build up arrays like this:
How can I initialize an array of objects whose constructor require two or more arguments?
But if your constructor takes a hardcoded list (as yours seem to), then there's been a bit of a fly in the ointment. While C++ can initialize ordinary arrays with values you code in directly, passing the ordinary array loses its length information. A vector would be better, but initializing them with hardcoded values is clunky:
What is the easiest way to initialize a std::vector with hardcoded elements?
You can see that people had pretty much the same complaint you did about having to write:
std::vector<int> ints;
ints.push_back(10);
ints.push_back(20);
ints.push_back(30);
That post lists some of the workarounds, but bleeding edge compilers (probably not what you're using) support:
std::vector<int> ints = {10, 20, 30};
Once you have those, it makes it extremely easy to do your "nested" style constructions.
As a final note: you seemed on an earlier comment to concretely ask about raw arrays vs vectors. For your interface you almost certainly want a vector. Here's a pitfall: using new xlsmain[100] on a raw array requires to remember to do a delete[] interface (and not just a regular delete interface):
delete vs delete[] operators in C++
Bear in mind there is also no realloc in C++ anyway. So if that's why you were dynamically allocating it, forget about that idea.
You can save yourself from trouble like this by just making interface a vector. You will be able to resize it if you ever need to, and also avoid hard-coding a so-called "Magic Number" into your program.
I've seen numerous arguments that using a return value is preferable to out parameters. I am convinced of the reasons why to avoid them, but I find myself unsure if I'm running into cases where it is unavoidable.
Part One of my question is: What are some of your favorite/common ways of getting around using an out parameter? Stuff along the lines: Man, in peer reviews I always see other programmers do this when they could have easily done it this way.
Part Two of my question deals with some specific cases I've encountered where I would like to avoid an out parameter but cannot think of a clean way to do so.
Example 1:
I have a class with an expensive copy that I would like to avoid. Work can be done on the object and this builds up the object to be expensive to copy. The work to build up the data is not exactly trivial either. Currently, I will pass this object into a function that will modify the state of the object. This to me is preferable to new'ing the object internal to the worker function and returning it back, as it allows me to keep things on the stack.
class ExpensiveCopy //Defines some interface I can't change.
{
public:
ExpensiveCopy(const ExpensiveCopy toCopy){ /*Ouch! This hurts.*/ };
ExpensiveCopy& operator=(const ExpensiveCopy& toCopy){/*Ouch! This hurts.*/};
void addToData(SomeData);
SomeData getData();
}
class B
{
public:
static void doWork(ExpensiveCopy& ec_out, int someParam);
//or
// Your Function Here.
}
Using my function, I get calling code like this:
const int SOME_PARAM = 5;
ExpensiveCopy toModify;
B::doWork(toModify, SOME_PARAM);
I'd like to have something like this:
ExpensiveCopy theResult = B::doWork(SOME_PARAM);
But I don't know if this is possible.
Second Example:
I have an array of objects. The objects in the array are a complex type, and I need to do work on each element, work that I'd like to keep separated from the main loop that accesses each element. The code currently looks like this:
std::vector<ComplexType> theCollection;
for(int index = 0; index < theCollection.size(); ++index)
{
doWork(theCollection[index]);
}
void doWork(ComplexType& ct_out)
{
//Do work on the individual element.
}
Any suggestions on how to deal with some of these situations? I work primarily in C++, but I'm interested to see if other languages facilitate an easier setup. I have encountered RVO as a possible solution, but I need to read up more on it and it sounds like a compiler specific feature.
I'm not sure why you're trying to avoid passing references here. It's pretty much these situations that pass-by-reference semantics exist.
The code
static void doWork(ExpensiveCopy& ec_out, int someParam);
looks perfectly fine to me.
If you really want to modify it then you've got a couple of options
Move doWork so that's it's a member of ExpensiveCopy (which you say you can't do, so that's out)
return a (smart) pointer from doWork instead of copying it. (which you don't want to do as you want to keep things on the stack)
Rely on RVO (which others have pointed out is supported by pretty much all modern compilers)
Every useful compiler does RVO (return value optimization) if optimizations are enabled, thus the following effectively doesn't result in copying:
Expensive work() {
// ... no branched returns here
return Expensive(foo);
}
Expensive e = work();
In some cases compilers can apply NRVO, named return value optimization, as well:
Expensive work() {
Expensive e; // named object
// ... no branched returns here
return e; // return named object
}
This however isn't exactly reliable, only works in more trivial cases and would have to be tested. If you're not up to testing every case, just use out-parameters with references in the second case.
IMO the first thing you should ask yourself is whether copying ExpensiveCopy really is so prohibitive expensive. And to answer that, you will usually need a profiler. Unless a profiler tells you that the copying really is a bottleneck, simply write the code that's easier to read: ExpensiveCopy obj = doWork(param);.
Of course, there are indeed cases where objects cannot be copied for performance or other reasons. Then Neil's answer applies.
In addition to all comments here I'd mention that in C++0x you'd rarely use output parameter for optimization purpose -- because of Move Constructors (see here)
Unless you are going down the "everything is immutable" route, which doesn't sit too well with C++. you cannot easily avoid out parameters. The C++ Standard Library uses them, and what's good enough for it is good enough for me.
As to your first example: return value optimization will often allow the returned object to be created directly in-place, instead of having to copy the object around. All modern compilers do this.
What platform are you working on?
The reason I ask is that many people have suggested Return Value Optimization, which is a very handy compiler optimization present in almost every compiler. Additionally Microsoft and Intel implement what they call Named Return Value Optimization which is even more handy.
In standard Return Value Optimization your return statement is a call to an object's constructor, which tells the compiler to eliminate the temporary values (not necessarily the copy operation).
In Named Return Value Optimization you can return a value by its name and the compiler will do the same thing. The advantage to NRVO is that you can do more complex operations on the created value (like calling functions on it) before returning it.
While neither of these really eliminate an expensive copy if your returned data is very large, they do help.
In terms of avoiding the copy the only real way to do that is with pointers or references because your function needs to be modifying the data in the place you want it to end up in. That means you probably want to have a pass-by-reference parameter.
Also I figure I should point out that pass-by-reference is very common in high-performance code for specifically this reason. Copying data can be incredibly expensive, and it is often something people overlook when optimizing their code.
As far as I can see, the reasons to prefer return values to out parameters are that it's clearer, and it works with pure functional programming (you can get some nice guarantees if a function depends only on input parameters, returns a value, and has no side effects). The first reason is stylistic, and in my opinion not all that important. The second isn't a good fit with C++. Therefore, I wouldn't try to distort anything to avoid out parameters.
The simple fact is that some functions have to return multiple things, and in most languages this suggests out parameters. Common Lisp has multiple-value-bind and multiple-value-return, in which a list of symbols is provided by the bind and a list of values is returned. In some cases, a function can return a composite value, such as a list of values which will then get deconstructed, and it isn't a big deal for a C++ function to return a std::pair. Returning more than two values this way in C++ gets awkward. It's always possible to define a struct, but defining and creating it will often be messier than out parameters.
In some cases, the return value gets overloaded. In C, getchar() returns an int, with the idea being that there are more int values than char (true in all implementations I know of, false in some I can easily imagine), so one of the values can be used to denote end-of-file. atoi() returns an integer, either the integer represented by the string it's passed or zero if there is none, so it returns the same thing for "0" and "frog". (If you want to know whether there was an int value or not, use strtol(), which does have an out parameter.)
There's always the technique of throwing an exception in case of an error, but not all multiple return values are errors, and not all errors are exceptional.
So, overloaded return values causes problems, multiple value returns aren't easy to use in all languages, and single returns don't always exist. Throwing an exception is often inappropriate. Using out parameters is very often the cleanest solution.
Ask yourself why you have some method that performs work on this expensive to copy object in the first place. Say you have a tree, would you send the tree off into some building method or else give the tree its own building method? Situations like this come up constantly when you have a little bit off design but tend to fold into themselves when you have it down pat.
I know in practicality we don't always get to change every object at all, but passing in out parameters is a side effect operation, and it makes it much harder to figure out what's going on, and you never really have to do it (except as forced by working within others' code frameworks).
Sometimes it is easier, but it's definitely not desirable to use it for no reason (if you've suffered through a few large projects where there's always half a dozen out parameters you'll know what I mean).
In C++, whenever a function creates many (hundreds or thousands of) values, I used to have the caller pass an array that my function then fills with the output values:
void computeValues(int input, std::vector<int>& output);
So, the function will fill the vector output with the values it computes. But this is not really good C++ style, as I'm realizing now.
The following function signature is better because it doesn't commit to using a std::vector, but could use any container:
void computeValues(int input, std::insert_iterator<int> outputInserter);
Now, the caller can call with some inserter:
std::vector<int> values; // or could use deque, list, map, ...
computeValues(input, std::back_inserter(values));
Again, we don't commit to using std::vector specifically, which is nice, because the user might just need the values in a std::set etc. (Should I pass the iterator by value or by reference?)
My question is: Is the insert_iterator the right or standard way to do it? Or is there something even better?
EDIT: I edited the question to make it clear that I'm not talking about returning two or three values, but rather hundreds or thousands. (Imagine you have return all the files you find in a certain directory, or all the edges in a graph etc.)
Response to Edit: Well, if you need to return hundreds and thousands if values, a tuple of course would not be the way to go. Best pick the solution with the iterator then, but it's best not use any specific iterator type.
If you use iterators, you should use them as generic as possible. In your function you have used an insert iterator like insert_iterator< vector<int> >. You lost any genericity. Do it like this:
template<typename OutputIterator>
void computeValues(int input, OutputIterator output) {
...
}
Whatever you give it, it will work now. But it will not work if you have different types in the return set. You can use a tuple then. Also available as std::tuple in the next C++ Standard:
boost::tuple<int, bool, char> computeValues(int input) {
....
}
If the amount of values is variadic and the type of the values is from a fixed set, like (int, bool, char), you can look into a container of boost::variant. This however implies changes only on the call-side. You can keep the iterator style of above:
std::vector< boost::variant<int, bool, char> > data;
computeValues(42, std::back_inserter(data));
You could return a smart pointer to a vector. That should work and no copy of the vector will be made.
If you don't want to keep the smart pointer for the rest of your program, you could simply create a vector before calling the function, and swap both vectors.
Actually, your old method of passing in the vector has a lot to recommend it -- it's efficient, reliable, and easy to understand. The disadvantages are real but don't apply equally in all cases. Are people really going to want the data in an std::set or list? Are they really going to want to use the long list of numbers without bothering to assign it to a variable first (one of the reasons to return something via 'return' rather than a parameter)? Being generic is nice, but there is a cost in your programming time that may not be redeemed.
If you ever have a group of objects, chances are you have at least a few methods that work on that group of objects (otherwise, what are you doing with them?)
If that's the case, it would make sense to have those methods in a class that contain both said objects and methods.
If that makes sense and you have such a class, return it.
I virtually never find myself thinking that I wish I could return more than one value. By the fact that a method should only do one small thing, your parameters and return values tend to have a relationship, and so are more often than not deserving of a class that contains them, so returning more than one value is rarely interesting (Maybe I wished for it 5 times in 20 years--each time I refactored instead, came up with a better result and realized my first attempt was sub-standard.)
One other option is boost::tuple: http://www.boost.org/doc/libs/1_38_0/libs/tuple/doc/tuple_users_guide.html
int x, y;
boost::tie(x,y) = bar();
A stadard container works for homogenous objects 9which you can return).
The standard library way is to abstract an algorithm from the container and use iterators to bridge the gap between.
If you need to pass more than a single type think of structs/classes.
My question is: Is the insert_iterator the right or standard way to do it?
Yes. Otherwise, if you are not going to have at least as many elements in your container as there will be computed values. This is not always possible, specially, if you want to write to a stream. So, you are good.
Your example with insert_iterator won't work, because insert_iterator is a template requiring a container for a parameter. You could declare it
void computeValues(int input, std::insert_iterator<vector<int> > outputInserter);
or
template<class Container>
void computeValues(int input, std::insert_iterator<Container> outputInserter);
The first will tie you back to a vector<int> implementation, without any obvious advantages over your initial code. The second is less restrictive, but implementing as a template will give you other constraints that might make it a less desirable choice.
I'd use something like
std::auto_ptr<std::vector<int> > computeValues(int input);
{
std::auto_ptr<std::vector<int> > r(new std::vector<int>);
r->push_back(...) // Hundreds of these
return r;
}
No copying overhead in the return or risk of leaking (if you use auto_ptr correctly in the caller).
I'd say your new solution is more general, and better style. I'm not sure I'd worry too much about style in c++, more about usability and efficiency.
If you're returning a lot of items, and know the size, using a vector would allow you to reserve the memory in one allocation, which may or may not be worth it.