Более короткий способ получить итератор для std :: vector - PullRequest
6 голосов
/ 21 сентября 2011

Допустим, у меня есть такой вектор.

std::vector<a_complicated_whatever_identifier *> *something
    = new std::vector<a_complicated_whatever_identifier *>;
// by the way, is this the right way to do this?

Теперь я хочу получить итератор для этого ... поэтому я бы сделал это следующим образом.

std::vector<a_complicated_whatever_identifier *>::iterator iter;

Но я считаю, что это слишком много для моего кода.Интересно, есть ли еще какой-нибудь краткий способ попросить итератор независимо от типа?

Я думал о чем-то вроде.

something::iterator iter;
    // OK, don’t laugh at me, I am still beginning with C++

Ну, это явно не получается, но ядумаю, вы поняли идею.Как это сделать или что-то подобное?

Ответы [ 6 ]

11 голосов
/ 21 сентября 2011

Обычно вы предоставляете свои контейнеры разумные определения типов, и тогда это просто:

typedef std::pair<int, Employee> EmployeeTag;
typedef std::map<Foo, EmployeeTag> SignInRecords;

for (SignInRecords::const_iterator it = clock_ins.begin(); ... )
           ^^^^^^^^^^^^^^^^^

Обычно, иметь удобный typedef для контейнера более практично и самодокументирующе, чтоявный typedef для итератора (представьте, что вы меняете контейнер).

С новым C ++ (11) вы можете сказать auto it = clock_ins.cbegin(), чтобы получить const-итератор.

8 голосов
/ 21 сентября 2011

Используйте typedef.

typedef std::vector<complicated *>::iterator complicated_iter

Затем установите их так:

complicated_iter begin, end;
7 голосов
/ 21 сентября 2011

В C ++ 11 вы сможете использовать auto.

auto iter = my_container.begin();

А пока просто используйте typedef для вектора:

typedef std::vector<a_complicated_whatever_identifier *> my_vector;
my_vector::iterator iter = my_container.begin();
1 голос
/ 21 сентября 2011

Вы должны редко иметь большую потребность / использование для непосредственного определения итератора.В частности, перебор коллекции должен обычно выполняться с помощью общего алгоритма.Если кто-то уже определил, что может выполнить эту работу, лучше всего ее использовать.Если нет, то лучше написать собственный алгоритм как алгоритм .В этом случае тип итератора становится параметром шаблона с любым именем, которое вы предпочитаете (обычно это что-то, относящееся хотя бы к категории итераторов):

template <class InputIterator>
void my_algorithm(InputIterator start, InputIterator stop) { 
    for (InputIterator p = start; p != stop; ++p) 
        do_something_with(*p);
}

Поскольку они уже упоминались, я укажучто IMO, typedef и новые auto в C ++ 11 (по крайней мере IMO) редко бывают хорошим ответом на эту ситуацию.Да, они могут устранить (или, по крайней мере, уменьшить) многословие в определении объекта типа итератора - но в этом случае это в основном просто лечение симптома, а не болезни.

В качестве отступления, яТакже отметим, что:

  1. Вектор указателей обычно является ошибкой.
  2. Динамическое выделение вектора еще более вероятно ошибка.

По крайней мере, сразу кажется, что вы, вероятно, уже привыкли к чему-то подобному Java, где вам всегда приходится использовать new для создания объекта.В C ++ это относительно необычно - в большинстве случаев вы просто хотите определить локальный объект, чтобы создание и удаление обрабатывались автоматически.

0 голосов
/ 21 сентября 2011

Если у вас есть недавний компилятор, я предлагаю дать c ++ 11 вращение. Большинство компиляторов поддерживают его в виде флага --std=c++0x. Вы можете делать все изящные вещи, связанные с выводом типа:

std::list<std::map<std::string, some_complex_type> > tables;

for (auto& table: tables)
{
     std::cout << table.size() << std::endl;
}

for (auto it = tables.begin(); it!= tables.end(); ++it)
{
     std::cout << it->size() << std::endl;
}

Также посмотрите на decltype и многие другие удобства:

// full copy is easy
auto clone = tables; 

// but you wanted same type, no data?
decltype(tables) empty;

Придуманный пример объединения typedef с приведенным выше:

typedef decltype(tables) stables_t;
typedef stables_t::value_type::const_iterator ci_t;
0 голосов
/ 21 сентября 2011

// кстати, это правильный способ сделать это?

То, что вы делаете, правильно. Лучший подход зависит от того, как вы хотите использовать этот вектор.

Но я считаю, что это слишком много для моего кода. Интересно, есть ли более краткий способ запросить итератор независимо от типа?

Да, вы можете определить вектор как тип:

typedef std::vector<a_complicated_whatever_identifier *> MyVector;
MyVector * vectPtr = new MyVector;
MyVector::iterator iter;
...