views:

166

answers:

6

Hi,

I have a class which has a private attribute vector rectVec;

class A {
private:
   vector<Rect> rectVec;
};

My question is how can I return a 'read-only' copy of my Vector? I am thinking of doing this:

class A {
public:
  const vect<Rect>& getRectVec() { return rectVect; }
}

Is that the right way? I am thinking this can guard against the callee modify the vector(add/delete Rect in vector), what about the Rect inside the vector?

+5  A: 

That's the normal way. const means "you cannot modify this". It also applies to the elements within the container.

A simple test:

#include <vector>

typedef std::vector<int> int_vec;

struct foo
{
    const int_vec& get(void)
    {
        return v;
    }

    int_vec v;
};

int main(void)
{
    foo f;
    f.v.push_back(1);
    f.v.push_back(2);
    f.v.push_back(3);

    f.get()[0] = 2; // nope
}

const_cast could be used to strip the const away, but you'd then end up with undefined behavior if you modified a variable through it:

int_vec& v = const_cast<int_vec&>(f.get()); // this is okay
v[0] = 0; // but now we've entered undefined behavior
GMan
If you must defend against const being cast away, and don't mind the (huge) performance penalty, you can return a copy of the vector. This way the caller can change it in any way they want and not affect the private vector. Simply return by value rather than reference.
Arkadiy
"end up with undefined behavior": Not exactly, because `v` is not declared as const in the first place.
AraK
@Arkadiy: It's already defended by leading to undefined behavior. Nobody should have to say or do anything more; those who wish to entered Undefined Behavior Land can surely perish.
GMan
@GMan as AraK said, it is only UB to cast away const-ness if the pointed-to/referred-to object was declared as const. Casting away constness on a pointer or reference to an object that is not itself const is perfectly well defined, although usually indicative of bad design.
Tyler McHenry
@AraK @Tyler: Hm, I always thought it was just any `const`, regardless of source. Oh well, I still maintain the "wtf are you doing" approach to disregarding `const_cast` worries.
GMan
Although AraK is right because your function `get` is not declared as const, use of 'const_cast' is a bad design anyway.
Kirill V. Lyadvinsky
It *can* be bad design. It can also be required in order to interface with a bad design.
Dennis Zickefoose
+1  A: 

That is the correct way, unless the user casts the constness away using const_cast.

AraK
+11  A: 

That is the right way, although you'll probably want to make the function const as well.

class A {
public:
  const vect<Rect>& getRectVec() const { return rectVect; }                           
};

This makes it so that people can call getRectVec using a const A object.

Peter Alexander
+1 for making `getRectVec` const.
big-z
A: 

So basically, using "const &" should indicate to any C++ programmer: You're really not supposed to modify this. If you're really paranoid, you'll have to clone the vector.

S.C. Madsen
+1  A: 

How about instead of returning a reference to your vector, return a new type that wraps the vector (contains a const reference to the vector) and exposes only the functionality you wish to allow the caller to access. I'm guessing this isn't much since you want to prevent mutability of the vector.

+2  A: 

in general this is bad practice. You are exposing your internal implementation to your callers. You are better of either returning a wrapper class instance (mentioned before) or exposing functions that get items or iterators (typedefed to match your implementation)

pm100