как передавать элементы контейнера в функцию
От: sci_reseacher  
Дата: 14.04.16 08:37
Оценка:
Нужно внутри функции получить доступ к элементам контейнера только на чтение. Как более правильно (эффективнее) это сделать?

В каких случаях следует использовать передачу ссылки на контейнер (как в f1), а в каких случаях итераторы (как в f2, почему-то в stl именно так):
void f1(const std::vector<int> & x){
    // ... used all elements of x
}

void f2(const std::vector<int>::const_iterator beg,const std::vector<int>::const_iterator end){
    // ... used all elements 
}

// ...
std::vector<int> y = {1,2,3};
f1(y);
f2(y.begin(),y.end());
Re: как передавать элементы контейнера в функцию
От: LaptevVV Россия  
Дата: 14.04.16 09:18
Оценка:
_>В каких случаях следует использовать передачу ссылки на контейнер (как в f1), а в каких случаях итераторы (как в f2, почему-то в stl именно так):
_>
_>void f1(const std::vector<int> & x){
_>    // ... used all elements of x
_>}

_>void f2(const std::vector<int>::const_iterator beg,const std::vector<int>::const_iterator end){
_>    // ... used all elements 
_>}

_>// ...
_>std::vector<int> y = {1,2,3};
_>f1(y);
_>f2(y.begin(),y.end());
_>

Второй способ более универсальный.
И совпадает с STL — привычно программисту. А значит — меньше случайных опечаток-ошибок.
И похоже, что в вашем случае просто можно подходящий стандартный алгоритм использовать (вместо писания своей функции)?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: как передавать элементы контейнера в функцию
От: andyp  
Дата: 14.04.16 09:37
Оценка:
Здравствуйте, sci_reseacher, Вы писали:

_>Нужно внутри функции получить доступ к элементам контейнера только на чтение. Как более правильно (эффективнее) это сделать?


Воспользуйся здравым смыслом:
Если ты решаешь, какие эл-ты контейнера обработать внутри функции, то передавай константную ссылку на контейнер, если вне — то константные итераторы.

_>В каких случаях следует использовать передачу ссылки на контейнер (как в f1), а в каких случаях итераторы (как в f2, почему-то в stl именно так):


Алгоритмы stl работают с кусочками контейнера, определенными пользователем, поэтому в них передаются итераторы.
Re: как передавать элементы контейнера в функцию
От: B0FEE664  
Дата: 14.04.16 09:38
Оценка:
Здравствуйте, sci_reseacher, Вы писали:

_>Нужно внутри функции получить доступ к элементам контейнера только на чтение. Как более правильно (эффективнее) это сделать?

На самом деле это два разных вопроса.
_>Как более правильно это сделать?
Правильно — это таким способом, чтобы ваши коллеги могли прочитать, что вы написали.

_>Как более (эффективнее) это сделать?

С помощью итераторов — они самые быстрые.

_>В каких случаях следует использовать передачу ссылки на контейнер (как в f1),

Передачу ссылки следует использовать когда требуется непоследовательный доступ к элементам или же для облегчения чтения (экономии кода):
inline void f1(const std::vector<int> & x)
{
    f2(std::begin(x), std::end(x));
}


_>а в каких случаях итераторы (как в f2, почему-то в stl именно так):

В стандартной библиотеке не так как в f2. В стандартной библиотеке используются шаблоны, что позволяет подставлять различные итераторы, например reverse_iterator'ы, которые можно использовать для доступа к элементам в обратном порядке.
Еще важно то, что при использовании итераторов возможно прохождение не по всем элементам контейнера, например:
f2(y.begin() + 1, y.end());


  Скрытый текст
_>
_>void f1(const std::vector<int> & x){
_>    // ... used all elements of x
_>}

_>void f2(const std::vector<int>::const_iterator beg,const std::vector<int>::const_iterator end){
_>    // ... used all elements 
_>}

_>// ...
_>std::vector<int> y = {1,2,3};
_>f1(y);
_>f2(y.begin(),y.end());
_>
И каждый день — без права на ошибку...
Re: как передавать элементы контейнера в функцию
От: watchmaker  
Дата: 14.04.16 09:53
Оценка: 2 (1)
Здравствуйте, sci_reseacher, Вы писали:


_>f1(y);
_>f2(y.begin(),y.end());
_>

Код эффективнее не станет от того, что ты вызовешь begin и end вне тела функции, а не внутри.

А в некоторых случаях передача контейнера может быть предпочтительнее: если у контейнера константный и неконстантный begin/end отличаются по устройству (например, из-за использования copy-on-write), то может быть выгоднее сначала навесить на контейнер const, а потом вызвать константный метод begin, чем сначала вызвать неконстантный begin, а потому полученный итератор преобразовывать в const_iterator. Впрочем такие случаи достаточно редки, и уж std::vector к ним, конечно, не относится.


_> Как более правильно (эффективнее) это сделать?

Зачем выбирать только один способ? Напиши два метода с одним именем:
void process(const std::vector<int>::const_iterator beg, const std::vector<int>::const_iterator end);

void process(const std::vector<int> & x) {
  return process(x.begin(), x.end());
}

Если у пользователя есть контейнер, то незачем его заставлять писать вспомогательные вызовы begin/end, если запись process(container) выглядит и короче, и понятнее.
А если возникнет всё же необходимость, то всегда можно вызвать более общую функцию: process(lower_bound(foo), upper_bound(bar)) или что там ещё понадобится.


_> почему-то в stl именно так

Это чтобы была возможность применить алгоритм только к части контейнера.
Re: Воcпользоваться идиомой Range (+)
От: Basil2 Россия https://starostin.msk.ru
Дата: 14.04.16 09:58
Оценка:
Здравствуйте, sci_reseacher, Вы писали:

_>В каких случаях следует использовать передачу ссылки на контейнер (как в f1), а в каких случаях итераторы (как в f2, почему-то в stl именно так):


Она позволит использовать оба способа.

(Способ с итераторами более универсален, но дает менее читаемый код. "Range" позволяет не выбирать между способами).
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[2]: как передавать элементы контейнера в функцию
От: _hum_ Беларусь  
Дата: 16.04.16 10:57
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>А в некоторых случаях передача контейнера может быть предпочтительнее: если у контейнера константный и неконстантный begin/end отличаются по устройству (например, из-за использования copy-on-write), то может быть выгоднее сначала навесить на контейнер const, а потом вызвать константный метод begin, чем сначала вызвать неконстантный begin, а потому полученный итератор преобразовывать в const_iterator.


уже есть cbegin()/cend()
Re: как передавать элементы контейнера в функцию
От: rg45 СССР  
Дата: 19.04.16 18:45
Оценка:
Здравствуйте, sci_reseacher, Вы писали:

_>Нужно внутри функции получить доступ к элементам контейнера только на чтение. Как более правильно (эффективнее) это сделать?


_>В каких случаях следует использовать передачу ссылки на контейнер (как в f1), а в каких случаях итераторы (как в f2, почему-то в stl именно так):

  <ccode>
_>
_>void f1(const std::vector<int> & x){
_>    // ... used all elements of x
_>}

_>void f2(const std::vector<int>::const_iterator beg,const std::vector<int>::const_iterator end){
_>    // ... used all elements 
_>}

_>// ...
_>std::vector<int> y = {1,2,3};
_>f1(y);
_>f2(y.begin(),y.end());
_>


using boost::iterator_range;
using std::vector;

void f3(iterator_range<vector<int>::const_iterator> range){

  for (auto value : range)
  {
    // use of elements of the range
  }
}

// ...
std::vector<int> y = {1,2,3};
f3(y);
f3(boost::make_iterator_range(boost::next(y.begin()), boost::prior(y.end())));
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 19.04.2016 18:56 rg45 . Предыдущая версия . Еще …
Отредактировано 19.04.2016 18:47 rg45 . Предыдущая версия .
Отредактировано 19.04.2016 18:46 rg45 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.