2009-11-23 3 views
4

У меня есть класс А, который содержит зЬй :: вектор, и я хотел бы дать доступ к вектору из вне класса А.STL итераторы в качестве возвращаемого значения

Первое, что пришло на ум это сделать функция get, которая возвращает итератор в вектор, но пройдите через вектор, мне понадобятся два итератора (начало и конец).

Мне было интересно, есть ли способ (техника или паттерны) для итерации всего вектора только с одним итератором? Или, возможно, какой-то другой способ получить доступ к вектору, конечно, без использования вектора в качестве возвращаемого значения :)

+4

Я надеюсь, вы понимаете, что разоблачение итератор вектора является способ отличается _ Нет than__ воздействия переменной-члена? (например, сама векторная переменная) На самом деле еще хуже. Возможно, вы указали указатель на частный член. –

ответ

1

STL представила идиому использования двух итераторов для описания диапазона. С тех пор begin() и end() являются геттерами. Преимущество этого заключается в том, что простая пара указателей на массив C может использоваться как идеальный итератор. Недостатком является то, что вам нужно носить с собой два объекта. C++ 1x будет, AFAIK, ввести концепцию диапазона, чтобы немного облегчить ее.

+0

В принципе, я хочу читать данные из вектора. – user44986

1

Похоже, что потенциально неразумно предоставлять такой доступ к вектору, но если вы хотите, чтобы не просто вернуть указатель или ссылку на вектор? (Возвращение самого вектора будет потенциально дорогостоящим.) В качестве альтернативы верните std::pair<> итераторов.

Итератор - это всего лишь индикатор для одного объекта; например, указатель может быть совершенно хорошим итератором с произвольным доступом. Он не несет информацию о том, в каком контейнере находится объект.

+2

Это похоже на общую идиому, которая диктует членам 'begin()' и 'end()' для доступа к базовому контейнеру. – sbi

+1

Выдавая только итераторы, вы не разрешаете изменять сам контейнер (добавление/удаление элементов). Кроме того, вы можете выдавать 'const_iterators' только для доступа только для чтения. Правильно ли это, что делать, зависит от того, что делает класс: может быть, он только хочет контролировать, как возникают вставки/стирания? – UncleBens

+2

Согласен; если вы должны предоставить доступ к вектору, просто верните ссылку. Сделайте это ссылкой на const, если вы хотите обеспечить доступ только для чтения. –

7

Почему бы не добавить к классу функцию begin() и end(), которая просто return v.begin(); и return v.end();? (Предполагается, что V ваш вектор.)

class MyVectorWrapper 
{ 
public: 
    // Give yourself the freedom to change underlying types later on: 
    typedef vector<int>::const_iterator const_iterator; 

    // Since you only want to read, only provide the const versions of begin/end: 
    const_iterator begin() const { return v.begin(); } 
    const_iterator end() const { return v.end(); } 

private: 
    // the underlying vector: 
    vector<int> v; 
} 

Тогда вы могли бы перебирать своего класса, как и любой другой:

MyVectorWrapper myV; 
for (MyVectorWrapper::const_iterator iter = myV.begin(); iter != myV.end(); ++i) 
{ 
    // do something with iter: 
} 
0

Это похоже на то, что вам нужно для достижения будет потенциальное нарушение так называемого Law of Demeter , Этот закон часто является излишним, но часто разумно подчиняться ему. Хотя вы можете предоставить доступ только для чтения, выдавая только константы-константы, вы по-прежнему рискуете, что ваши итераторы будут признаны недействительными (легко с векторами), если третье лицо не узнает об этом. Поскольку вы никогда не сможете предсказать, как ваша программа будет развиваться с течением времени, лучше избегать предоставления функций, которые могут быть использованы неправильно.
Общий девиз: сделать ваш интерфейс класса простым в использовании и трудно использовать. Вторая часть важна для общего качества продукции.

0

Подробнее:

template <typename T,typename A = std::allocator<T>> 
class yetAnotherVector 
{ 
public: 
typedef std::_Vector_iterator<T, A> iterator; 
protected: 
std::vector<T,A> mV; 
public: 
void add(const T& t) 
{ 
    if(!isExist(t))mV.push_back(t); 
} 
    bool isExist(const T& t) 
{ 
    std::vector<T,A>::iterator itr; 
    for(itr = mV.begin(); itr != mV.end(); ++itr) 
    { 
    if((*itr) == t) 
    { 
    return true; 
    } 
    } 
    return false; 
} 
iterator begin(void){return mV.begin();} 
iterator end(void){return mV.end();} 
}; 
+1

более подробная информация о решении поможет вместо простого кода –