michael
michael

Reputation: 110590

How to return a 'read-only' copy of a vector

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?

Upvotes: 28

Views: 12312

Answers (7)

Florian Tischler
Florian Tischler

Reputation: 178

I know its a rather old post but its one of the top google results when searching for "c++ read only vector". Thats why I want to post my approach nevertheless.

If you want the container itself to be const but not its elements you can use an approach similar to this one:

template<class Container>
class Enumerable
{
public:
    Enumerable(Container& container) : _container(container) {}

    auto begin() const { return _container.begin(); }
    auto end() const { return _container.end(); }

    const Container& GetContainer() const { return _container; }
    const Container* operator->() const { return &_container; }

private:
    Container& _container;
};

With that you can iterate over your container and modify its elements while ensuring the container itself stays the same. You may want to expose more functionality of the container by specializing the class for e.g. vectors by providing an indexing operator.

I'm not entirely sure if its good design to expose a container like that but its definitely a useful pattern for some scenarios.

Upvotes: 4

pm100
pm100

Reputation: 50190

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)

Upvotes: 1

user123456
user123456

Reputation:

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.

Upvotes: 1

S.C. Madsen
S.C. Madsen

Reputation: 5256

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.

Upvotes: 0

GManNickG
GManNickG

Reputation: 504033

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

Upvotes: 7

Peter Alexander
Peter Alexander

Reputation: 54280

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.

Upvotes: 37

Khaled Alshaya
Khaled Alshaya

Reputation: 96869

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

Upvotes: 2

Related Questions