开发者

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&g开发者_如何学编程t;& 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?


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.


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


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.


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


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.


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)


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜