preferable way to return a vector?

Hi, all -

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.

Thanks for any suggestions.
You could make the get() function return a const reference.
Can you give me a little more detail on this, please?
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.
Last edited on
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()?
If you want them to be able to "see" the vector but not modify it, then just return a const reference.
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 (unsigned int 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.
The main thing to worry about is who owns the vector:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 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 */ }
}

Last edited on
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.
You don't need the clear().
OK, thanks for the help, everyone.

1
2
// C++11 efficient
std::vector<int> getV() { std::vector<int> v; /* populate v */ return v; }


This is also the most efficient approach in C++98 (and C++03), unless you've resurrected a particularly ancient compiler. See: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

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.
Last edited on
Hi, Cubbi -

Would your example work if I used it in an assignment statement? In other words:

1
2
3
vector<int> myVector;
// push_back, etc.
myVector = getV();
It would work yes, but I don't think it can avoid a copy in this case.

Your code would work if getV() returned a reference too
mzimmers:

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.
Last edited on
I just re-read your earlier post:

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.
Topic archived. No new replies allowed.