Вектор как параметр функции c
Перейти к содержимому

Вектор как параметр функции c

  • автор:

Функции

right
Вектор, содержащий элементы, которые будут заменены, или вектор, элементы которого должны быть заменены на элементы вектора left .

left
Вектор, элементы которого должны поменяться местами с элементами вектора right .

Замечания

Функция шаблона — это алгоритм, специализированный для вектора класса контейнера для выполнения функции-члена left. vector::swap (right) . Это экземпляры частичного упорядочивания шаблонов функций компилятором. Если функции шаблона перегружены таким образом, чтобы совпадение шаблона с вызовом функции не было уникальным, компилятор выберет самую специализированную версию функции шаблона. Общая версия функции шаблона, template void swap(T&, T&) в классе алгоритма работает по назначению и является медленной операцией. Специализированная версия в каждом контейнере работает гораздо быстрее, так как она может работать с внутренним представлением класса контейнера.

Пример

Пример кода для функции-члена vector::swap см. в примере, использующего версию swap шаблона.

Передать вектор в функцию

Author24 — интернет-сервис помощи студентам

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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
#include #include using namespace std; void full(vectorint> vec) { for (int i = 0; i  10; i++) { vec[i] = i + 1; } } void vivod(vectorint> vec) { cout  ; for (int i = 0; i  10; i++) cout  <'\t'  [i]  ; } int main() { vectorint> vec(10); full(vec); vivod(vec); system("pause"); return 0; }

94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Как передать вектор в функцию?
Какими способами можно передать вектор в функцию? Например есть функция void asd() < .

Передать в функцию указатель на вектор
У меня есть вектор. Большой. Можно ли передать его так в ф-цию что бы не создавалась копия и что бы.

Передать итератор на шаблонный вектор в функцию
Здравствуйте. Есть два вектора std::vector<Player> players; // Player — структура с двумя.

Как передать вектор векторов в функцию?
Здравсвтуйте, проблема заключается в том, что при компиляции int func(int root, vector<.

«C with Classes»
1641 / 1398 / 523
Регистрация: 16.08.2014
Сообщений: 5,857
Записей в блоге: 1
gogaloh,

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
#include #include using namespace std; void full(vectorint>& vec) { for (int i = 0; i  10; i++) { vec[i] = i + 1; } } void vivod(const vectorint>& vec) { cout  ; for (int i = 0; i  10; i++) cout  <'\t'  [i]  ; } int main() { vectorint> vec(10); full(vec); vivod(vec); system("pause"); return 0; }

Вектор как параметр функции c

Вектор представляет контейнер, который содержит коллекцию объектов одного типа. Для работы с векторами необходимо включить заголовок:

#include

Определим простейший вектор:

std::vector numbers;

В угловых скобках указывается тип, объекты которого будут храниться в векторе. То есть вектор numbers хранит объекты типа int. Однако такой вектор пуст. Он не содержит никаких элементов.

Но мы можем инициализировать вектор одним из следующих способов:

std::vector v1; // пустой вектор std::vector v2(v1); // вектор v2 - копия вектора v1 std::vector v3 = v1; // вектор v3 - копия вектора v1 std::vector v4(5); // вектор v4 состоит из 5 чисел, каждое число равно 0 std::vector v5(5, 2); // вектор v5 состоит из 5 чисел, каждое число равно 2 std::vector v6; // вектор v6 состоит из чисел 1, 2, 4, 5 std::vector v7 = ; // вектор v7 состоит из чисел 1, 2, 3, 5

Важно понимать отличие в данном случае круглых скобок от фигурных:

std::vector v1(5); // вектор состоит из 5 чисел, каждое число в векторе равно 0 std::vector v2; // вектор состоит из одного числа, которое равно 5 std::vector v3(5, 2); // вектор состоит из 5 чисел, каждое число равно 2 std::vector v4; // вектор состоит из двух чисел 5 и 2

При этом можно хранить в векторе элементы только одного типа, который указан в угловых скобках. Значения других типов в вектор сохранить нельзя, как например, в следующем случае:

std::vector v;

Обращение к элементам и их перебор

Для обращения к элементам вектора можно использовать разные способы:

  • [index] : получение элемента по индексу (также как и в массивах), индексация начинается с нуля
  • at(index) : функция возращает элемент по индексу
  • front() : возвращает первый элемент
  • back() : возвращает последний элемент

Выполним перебор вектора и получим некоторые его элементы:

#include #include int main() < std::vectornumbers ; int first = numbers.front(); // 1 int last = numbers.back(); // 5 int second = numbers[1]; // 2 std::cout << "first: " << first << std::endl; std::cout << "second: " << second << std::endl; std::cout << "last: " << last << std::endl; numbers[0] = 6; // изменяем значение for(int n : numbers) std::cout << n << "\t"; // 6 2 3 4 5 std::cout

При этом следует учитывать, что индексация не добавляет элементов. Например, если вектор содержит 5 элементов, то мы не можем обратиться к шестому элементу:

std::vector numbers ; numbers[5] = 9;

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

Чтобы избежать подобных ситуаций, можно использовать функцию at() , которая хотя также возвращает элемент по индексу, но при попытке обращения по недопустимому индексу будет генерировать исключение out_of_range :

#include #include #include int main() < std::vectornumbers < 1, 2, 3, 4, 5>; try < int n = numbers.at(8); >catch (std::out_of_range e) < std::cout >

Язык C++

Давайте напишем функцию add_item , которая принимает контейнер vector и добавляет в конец контейнера новый элемент. Мы могли бы начать со следующего кода:

#include #include #include using namespace std; // Здесь есть проблема void add_item(vectorstring> vec)  vec.push_back("New item!"); > int main()  vectorstring> vec; add_item(vec); for (string s : vec)  cout  <s  <'\n'; > return 0; > 

Если мы скомпилируем и запустим эту программу, то обнаружим, что после вызова функции add_item контейнер vec остался пустым. Проблема в том, что мы передали в функцию копию объекта vec . Внутри функции к этой копии был добавлен новый элемент, а после выхода из функции копия была удалена.

Следующий вариант нашей программы уже будет делать то что мы хотим:

// Здесь есть проблема vectorstring> add_item(vectorstring> vec)  vec.push_back("New item!"); return vec; > int main()  vectorstring> vec; vectorstring> vec2 = add_item(vec); for (string s : vec2)  cout  <s  <'\n'; > return 0; > 

Такая реализация, однако, является очень плохой идеей. Мы всего лишь хотели добавить один элемент в вектор, а вместо этого получили копию вектора с добавленным новым элементом. Помимо неверной логики работы, мы получили потенциальную проблему с производительностью: вместо константного времени мы тратим линейное время на добавление элемента в вектор.

Правильное решение нашей задачи в C++ выглядит следующим образом:

void add_item(vectorstring>& vec)  vec.push_back("New item!"); > int main()  vectorstring> vec; add_item(vec); for (string s : vec)  cout  <s  <'\n'; > return 0; > 

Символ амперсанд & позволяет передать в функцию ссылку на параметр. Работа с параметром внутри функции не изменяется, но вместо копии мы имеем дело именно с тем объектом, который был передан в функцию. Таким образом, мы избавились от лишнего копирования и реализовали правильную логику работы программы.

Рассмотрим другой пример. Допустим, мы хотим передать вектор в функцию, которая будет анализировать элементы вектора, но не будет его изменять. Например:

// Здесь есть проблема int count_greetings(vectorstring>& vec)  int counter = 0; for (string s : vec)  if (s == "Hello")  ++counter; > > return counter; > 

Мы уже достаточно грамотные и сразу передали вектор по ссылке, чтобы избежать ненужного копирования. Однако в текущем виде функция count_greetings имеет другую, более тонкую, проблему. Если мы нарушим договоренность и изменим вектор внутри функции count_greetings , то компилятор не увидит в этом проблемы. Проблему будем искать мы, когда поймем, что в каком-то месте нашей программы происходит неправильная манипуляция с вектором.

Хорошим стилем в данном случае является передача параметра по константной ссылке:

int count_greetings(const vectorstring>& vec)  int counter = 0; for (const string& s : vec)  if (s == "Hello")  ++counter; > > return counter; > 

Теперь компилятор не позволит изменить объект vec внутри функции count_greetings . Кроме того, теперь в коде явно выражена мысль о том, что объект передается в функцию только для чтения. Такой код проще читать и понимать логику его работы. Обратите внимание, что мы воспользовались константной ссылкой при определении переменной в цикле for . Здесь мы имеем дело с аналогичной ситуацией: в предыдущей версии в переменную s по очереди копировался каждый элемент вектора. Теперь же мы перебираем в цикле константные ссылки на объекты, не копируя их.

Иногда необходимо изменять элементы вектора в цикле. В таком случае необходимо использовать неконстантную ссылку:

for (string& s : vec)  s.push_back('!'); > 

Передача константной ссылки на объект в функцию, которая не имеет право изменять объект, имеет смысл только в том случае, если копирование объекта является дорогой операцией. В частности, нет никакого смысла в передаче по ссылке объектов int или double . Это наоборот может привести к потере производительности. Если же мы имеем дело со сложным объектом, таким как string или любым контейнером, то передача по константой ссылке является единственным верным решением.

Использование ссылок в C++ не ограничивается передачей параметров в функции, но с этого примера проще всего начать знакомство со ссылками. Ключевое слово const также имеет разнообразные применения в C++. О некоторых из них мы поговорим в дальнейшем.

Резюме

Мы обсудили три способа передачи параметров в функцию:

  • передача копии
  • передача по ссылке
  • передача по константной ссылке

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

Источники

  • isocpp.org/wiki/faq/references

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *