-
July 3rd, 2010, 03:34 PM
#1
Returning a vector by value or by reference
Hi,
I am designing a class that has a vector as a private member. My class also has a member function that returns the vector. I am trying to decide if this function should return a copy of the private vector or a reference to it:
Code:
#include <vector>
using namespace std;
class A {
public:
vector<int> numbers1() {
return _numbers;
}
vector<int>& numbers2() {
return _numbers;
}
private:
vector<int> _numbers;
};
I would like to allow users to iterate thru the vector using numbers2().begin() and numbers2().end() directly (Note that this wouldn't work using number1 since both expressions return a different copy of the vector). But I've heard that I should avoid returning handles to object internals because of possible dangling handlers. I would like to know the thoughts of this group.
Thank you.
-
July 3rd, 2010, 03:37 PM
#2
Re: Returning a vector by value or by reference
But I've heard that I should avoid returning handles to object internals because of possible dangling handlers.
To a certain extent that's good advice, but don't take it too far. Requiring the user of the class to have some common sense like "don't destroy the object while iterating over it" isn't a bad thing. The rule of thumb is: do as the STL containers do. Obviously, you can't destroy one of them while iterating over it, right?
However, you might consider whether you want to return by reference, or whether const reference is most appropriate.
-
July 3rd, 2010, 03:47 PM
#3
Re: Returning a vector by value or by reference
Another thing to consider: would it be more appropriate to return begin and end iterators instead?
-
July 4th, 2010, 12:38 AM
#4
Re: Returning a vector by value or by reference
Originally Posted by roddomi
But I've heard that I should avoid returning handles to object internals because of possible dangling handlers.
Why not just return a couple of const iterators, like,
Code:
class A {
public:
std::vector<int>::const_iterator begin() {return v.cbegin();}
std::vector<int>::const_iterator end() {return v.cend();}
private:
std::vector<int> v;
};
You expose the internal data structure but at least users cannot change the data.
The standard approach to better encapsulation is to offer a getter access method like,
Code:
class A {
public:
int get(int i) {return v[i];}
int size() {v.size();}
private:
std::vector<int> v;
};
Yet another approach is to pass in a functor object. A method (for example operator()) of the functor is called with all ints of the vector one by one. This offers good encapsulation because users never know how the ints are actually stored internally. This approach is sometimes called "inner iteration".
Code:
class A {
public:
template <typename FUNCTOR>
void iterate(FUNCTOR& f) {
for (std::vector<int>::const_iterator p=v.cbegin(); p!=v.cend(); ++p) f(*p);
}
private:
std::vector<int> v;
};
//
class Sum_Functor {
public:
Sum_Functor() : sum(0) {}
int sum;
void operator() (int i) {
sum += i;
}
};
//
A a;
Sum_Functor sf;
a.iterate(sf);
int s = sf.sum;
Last edited by nuzzle; July 5th, 2010 at 02:38 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|