This isn't so much a "how to" question, as a matter of "good" programming technique.
I have a class that produces a series of values when I call its main routine. My programming convention so far has been to return computed values through a get() function. If I adhere to my convention, this particular get() would need to return a vector by reference (if this is even possible).
One alternative is to have the get() return one element at a time, but this is less than desirable. I'd much rather return the entire vector as a unit.
What do you think: should I ignore my convention and return the values through a vector parameter in the main function? Or, is there some clever way of doing this with a get()? I want the calling program to retain full control of the memory management of the vector.
If I understand it correctly you have a class that contains a vector and you want to access that vector from outside.
By returning a const reference you allow the vector to be accessed from outside without having to copy the vector. The vector is protected from changes outside the class because get() returns a const reference.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include <vector>
#include <iostream>
struct A
{
A(){v.push_back(3);v.push_back(5);}
const std::vector<int>& get() const {return v;}
std::vector<int> v;
};
int main()
{
A a;
const std::vector<int>& v = a.get();
for (std::size_t i = 0; i < v.size(); i++)
{
std::cout << v[i] << std::endl;
}
}
For efficiency, I would normally populate a reference to the std::vector passed as a parameter. However, the new C++ standard (C++11) makes returning a locally created vector very efficient, so now it is just as efficient to return a locally created vector.
Thanks for the suggestions. I'm still relatively new to the C++ "culture," if you will. Which of the above suggestions is preferable in your minds for a production application? Ultimate performance isn't a priority; I'd prefer to focus on code clarity.
I think Galik's suggestion is good if you create the vector inside the function itself. In this case you can return by value and it will not need to make any expensive copies (assuming an up to date compiler). You can't return a reference anyway because the vector will get destroyed after the function ends, leaving an invalid reference.
Returning a (const) reference makes more sense when the vector is stored somewhere so the vector stays alive after the function has returned. If you returned the vector by value in this case a copy can't normally be avoided.
OK, so in this case, the vector and its elements are created in the containing class. I'd like the get() call to the included class to populate the existing elements, but not create (push_back) any new ones. Does it make the most sense, then, to just pass the vector by reference to the get()?
Oh, I can tell I'm not doing a very good job of explaining this.
Class A contains an object of Class B.
Class B produces a series of outputs, which I'd like to get all at once with a get() call.
I'd like the output produced by B::get() to go into a pre-existing structure, so B does indeed need to modify the contents of the vector.
I'm getting the impression that the most straightforward way to do this is:
1 2 3 4 5 6 7
void DemodNyq::get(vector<int32_t>& v)
{
for (unsignedint i = 0; i < v.size(); ++i)
{
v.at(i) = cells.at(i)->get();
}
}
The only drawback to this is that B's get() function now behaves a little differently from all the others, in that the returned stuff is through a parameter, not the return argument, but I can live with this if it's the least of all evils.
// If the vector is owned by the class then you can return
// a const reference to it (assuming you don't want to modify it)
class A
{
std::vector<int> v;
public:
const std::vector<int>& getV() { return v; }
};
// If the vector is created by the function itself then you can
// simply return it by value (assuming C++11).
// However if your compiler is not C++11 ready then you may want to
// pass in a reference.
class B
{
public:
// C++11 efficient
std::vector<int> getV() { std::vector<int> v; /* populate v */ return v; }
// C++03 efficient
void getV(std::vector& v) { v.clear(); /* populate v */ }
}
Yeah, in this case, the vector is owned by the containing class, but I want the contained class to modify its contents (though not its size). It appears that the best approach is what we came to in the last few posts. I don't see the need for a clear, since I can just overwrite the contents, or...is that bad practice with vectors? Once created, its size should remain fixed.
In general, best practice is for the code to reflect the semantics: return is to produce a new value, reference/iterator argument is to modify an already-existing value.
In case of using the return value as an argument in assignment, myVector becomes the new owner of v's dynamic array, myVector's old dynamic array is deleted. No copies are made (assuming compiler with basic optimization enabled). In C++11 it's called 'move assignment', but it's just a new name and formalism for the long standing existing practice.
In this case it is indeed more efficient to pass by reference: if you're not changing the array size, you're avoiding allocations.
In general, best practice is for the code to reflect the semantics: return is to produce a new value, reference/iterator argument is to modify an already-existing value.
I think this is the answer I was looking for. Thanks...good to have you on this forum.