функция, возвращающая итератор в C ++ - PullRequest
10 голосов
/ 11 января 2012

Ниже приведен метод Java, который возвращает итератор

vector<string> types;

// some code here

Iterator Union::types() 
{
    return types.iterator();
}

Я хочу перевести этот код на C ++. Как я могу вернуть итератор вектора из этого метода?

Ответы [ 6 ]

15 голосов
/ 11 января 2012

Это вернет итератор к началу types:

std::vector<string>::iterator Union::types() 
{
    return types.begin();
}

Однако, вызывающий должен знать end() вектора types. В Java Iterator есть метод hasNext(): его нет в C ++.

Вы можете изменить Union::types(), чтобы получить диапазон:

std::pair<std::vector<std::string>::iterator, 
          std::vector<std::string>::iterator> Union::types()
{
    return std::make_pair(types.begin(), types.end());
}

std::pair<std::vector<std::string>::iterator, 
          std::vector<std::string>::iterator> p =  Union::types();

for (; p.first != p.second; p.first++)
{
}
9 голосов
/ 11 января 2012

Вам понадобится метод begin и end:

std::vector<string>::iterator Union::begin()
{
  return types.begin();
}

std::vector<string>::iterator Union::end()
{
  return types.end();
}

Для полноты вы можете также хотеть иметь const версии

std::vector<string>::const_iterator Union::begin()const
{
  return types.begin();
}

std::vector<string>::const_iterator Union::end()const
{
  return types.end();
}
3 голосов
/ 11 января 2012

Вернуть итератор легко. Например, вы можете вернуть первый итератор в векторных типах:

std::vector<std::string> types;

// some code here

std::vector<std::string>::iterator Union::returnTheBeginIterator() 
{
    return types.begin();
}

Java против C ++

Но итераторы C ++ не являются итераторами Java: они не используются одинаково.

В Java (IIRC) вы больше похожи на перечислитель, то есть вы используете метод «next» для перехода от одного элемента к следующему. Таким образом, возвращения Java-итератора достаточно для итерации от начала до конца.

В C ++ итератор спроектирован так, чтобы вести себя как супер-указатель. Таким образом, он обычно «указывает» на значение, и, используя операторы ++, - и т. Д. (В зависимости от точного типа итератора), вы можете переместить итератор в «точку» на следующий, предыдущий и т. Д. . значение в контейнере.

Давайте повторим!

Обычно вы хотите выполнить итерацию от начала до конца.

Для этого вам нужно вернуть либо всю коллекцию (как "const", если вы хотите, чтобы она была только для чтения), и позволить пользователю выполнять итерацию так, как он хочет.

Или вы можете вернуть два итератора, один для начала и один для конца. Таким образом, вы могли бы иметь:

std::vector<std::string>::iterator Union::typesBegin() 
{
    return types.begin();
}

std::vector<std::string>::iterator Union::typesEnd() 
{
    return types.end();
}

И, вы можете перебирать от начала до конца, в C ++ 03:

// alias, because the full declaration is too long
typedef std::vector<std::string> VecStr ;

void foo(Union & p_union)
{
   VecStr::iterator it = p_union.typesBegin() ;
   VecStr::iterator itEnd = p_union.typesEnd() ;

   for(; it != itEnd; ++it)
   {
       // here, "*it" is the current string item
       std::cout << "The current value is " << *it << ".\n" ;
   }
}

C ++ 11 версия

Если вы предоставите полный контейнер вместо только его итераторов, в C ++ 11 это станет проще, поскольку вы можете использовать цикл range-for (как foreach в Java и C #):

void foo(std::vector<std::string> & p_types)
{
   for(std::string & item : p_types)
   {
       // here, "item " is the current string item
       std::cout << "The current value is " << item  << ".\n" ;
   }
}

P.S .: Johannes Schaub - litb прав в использовании квалификатора "const" всякий раз, когда это возможно. Я сделал это не потому, что хотел избежать разбавления кода, но, в конце концов, «const» - ваш друг.

3 голосов
/ 11 января 2012

Союз - это контейнер его членов.Я бы использовал begin и end, чтобы вернуть итераторы первому и последнему элементам соответственно.

Список типов не является IMO основным итерируемым свойством объединения.Поэтому я бы сам использовал следующее и зарезервировал простые begin и end для самих данных участника.

std::vector<string>::const_iterator Union::types_begin() const {
  return types.begin();
}

std::vector<string>::const_iterator Union::types_end() const {
  return types.end();
}
2 голосов
/ 11 января 2012

Предполагая, что types является атрибутом класса Union, хороший, STL-совместимый способ справиться с этим:

class Union
{
std::vector< std::string > types
public:
typedef std::vector< std::string >::iterator iterator;
iterator begin() { return types.begin(); }
iterator end() { return types.end(); }

};
0 голосов
/ 11 января 2012

Вы можете сделать это, как показано ниже

std::vector<std::string> types

std::vector<std::string>::iterator Union::types(){
    return types.begin();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...