Как вернуть "только для чтения" копию вектора
У меня есть класс, который имеет частный атрибут vector rectVec;
class A {
private:
vector<Rect> rectVec;
};
Мой вопрос в том, как я могу вернуть копию только для чтения моего вектора?
Я думаю об этом:
class A {
public:
const vect<Rect>& getRectVec() { return rectVect; }
}
Правильно ли это?
Я думаю, что это может защитить от вызываемого изменения вектора (добавить/удалить Rect в векторе), что относительно Rect внутри вектора?
Ответы
Ответ 1
Это правильный путь, хотя вы, вероятно, захотите также сделать функцию const
.
class A {
public:
const vect<Rect>& getRectVec() const { return rectVect; }
};
Это делает так, что люди могут вызывать getRectVec
с помощью объекта const A
.
Ответ 2
Это нормальный путь. const
означает "вы не можете изменить это". Это также относится к элементам внутри контейнера.
Простой тест:
#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
можно использовать для удаления const
, но в итоге вы получите поведение undefined, если вы измените переменную через него:
int_vec& v = const_cast<int_vec&>(f.get()); // this is okay
v[0] = 0; // but now we've entered undefined behavior
Ответ 3
Это правильный путь, если пользователь не отбрасывает константу с помощью const_cast
.
Ответ 4
в целом это плохая практика. Вы подвергаете свою внутреннюю реализацию своим абонентам. Вам лучше либо возвращать экземпляр класса-оболочки (упомянутый выше), либо выставлять функции, которые получают элементы или итераторы (typedefed, чтобы соответствовать вашей реализации)
Ответ 5
Как вместо того, чтобы возвращать ссылку на ваш вектор, верните новый тип, который обертывает вектор (содержит ссылку на const для вектора) и предоставляет только те функции, которые вы хотите разрешить вызывающему абоненту. Я предполагаю, что это не так много, потому что вы хотите предотвратить изменчивость вектора.
Ответ 6
Я знаю его довольно старый пост, но его один из лучших результатов Google при поиске "С++ read only vector". Вот почему я хочу опубликовать свой подход, тем не менее.
Если вы хотите, чтобы контейнер сам был const, а не его элементы, вы можете использовать подход, подобный этому:
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;
};
С помощью этого вы можете перебирать контейнер и изменять его элементы, гарантируя, что сам контейнер остается прежним. Возможно, вам захочется предоставить больше функциональности контейнера, специализируясь на классе, например. векторов, предоставляя оператор индексирования.
Я не совсем уверен, может ли его хороший дизайн выставить такой контейнер, но он определенно полезен для некоторых сценариев.
Ответ 7
Итак, в основном, используя "const &" должен указывать любому программисту на С++: вы действительно не должны изменять это. Если вы действительно параноик, вам придется клонировать вектор.