Как заполнить vector c из файла

Обновлено: 04.07.2024

Столкнулся с проблемой, нужно вектор ввести в файл, а потом вывести оттуда.
Делаю я как написано в книге (блочный ввод/вывод), но там не для векторов, а для массива.

Записываю в файл:

Извлекаю из файла


Синтаксической ошибки нет, но. я коментну строку с ошибкой.

Как сделать это правильно?

Здравствуйте, Psihadelic, Вы писали:

Здравствуйте, Psihadelic, Вы писали:

P>Столкнулся с проблемой, нужно вектор ввести в файл, а потом вывести оттуда.
P>Делаю я как написано в книге (блочный ввод/вывод), но там не для векторов, а для массива.

А если бы в книге был не массив, а указатель (на массив)? Получился бы точно такой же эффект с вылетом.

vector — это объект, хранящий свой массив по указателю.
Записывать out.write(&MasSt, sizeof(MasSt)) бессмысленно, так в файле окажется несколько адресов и чисел, но не сами элементы.
После чтения, эти адреса будут указывать в никуда.


¹) только в том случае, если students — это POD-тип. К примеру, std::string и std::vector — не POD.

Спасибо большое! Конечно не всё понял, но спасибо! Про сериализацию почитал на МСДН, теперь хоть знаю что это такое, но в суть не очень вник, инфы было мало, а читать форум мне пока ещё сложно (не тот уровень знаний).
Не знаю, что такое POD-тип, но у меня students это простой класс.

Хочу задать парочку вопросов:
1) что такое size_t ?
2) out.write((const char*)&count, sizeof(count)); // сохраняем количество
зачем нам сохранять количество элементов и можно ли написать это одной строкой?
3) зачем читать количество? in.read((char*)&count, sizeof(count)); // читаем количество
4) MasSt.resize(count); // резервируем
резервируем. кол-во элементов, но зачем резервируем, куда и что вообще это значит?)

Здравствуйте, Psihadelic, Вы писали:

P>Спасибо большое! Конечно не всё понял, но спасибо! Про сериализацию почитал на МСДН, теперь хоть знаю что это такое, но в суть не очень вник, инфы было мало, а читать форум мне пока ещё сложно (не тот уровень знаний).

P>Не знаю, что такое POD-тип, но у меня students это простой класс.

Гугл в помощь.
Если коротко, это такой тип, объекты которого можно копировать побайтово. Plain Old Data — "старые добрые простые данные".


P>Хочу задать парочку вопросов:
P>1) что такое size_t ?

Стандартный тип для представления размеров данных.
Аналог unsigned int, грубо говоря. (Тонкости возникают на 64-битных платформах LLP64 и LP64, где sizeof(int)=4, sizeof(size_t)=8).

P>2) out.write((const char*)&count, sizeof(count)); // сохраняем количество
P> зачем нам сохранять количество элементов и можно ли написать это одной строкой?

Затем, что мы же должны оставить потомкам сведения: сколько элементов в массиве.
У нас есть 3 стратегии: префиксная, инфиксная, суффиксная.
Префиксная — записать "сколько", а потом элементы.
Суффиксная — записать элементы и в конце особый завершающий элемент. Например, студента с пустым именем.
Инфиксная — записать последовательность, в которой чередуются маркеры (продолжение/конец) и элементы: что-то вроде "+", элемент, "+", элемент, "+", элемент, "-".

Соответственно, чтение
Префиксная — прочитать "сколько", затем прочитать столько элементов подряд.
Суффиксная — читать элементы поштучно и проверять, не является ли очередной признаком конца.
Инфиксная — читать маркеры и элементы поштучно; когда прочитан маркер конца, не пытаться прочесть следующий элемент (его там нет).

P>3) зачем читать количество? in.read((char*)&count, sizeof(count)); // читаем количество

Чтобы узнать, сколько элементов следует за ним в файле.
Только в том случае, если размер элемента в файле постоянный, и ничего иного в файле нет, — можно взять размер файла и поделить на размер элемента.

P>4) MasSt.resize(count); // резервируем
P> резервируем. кол-во элементов, но зачем резервируем, куда и что вообще это значит?)

Выделяем память под элементы. Создаём массив.
И в этот массив будем читать файл.

Думаю, есть смысл сперва прочитать про vector и т.п., а только потом уже бросаться кодить.
Иначе будешь ловить один access violation за другим.

Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Psihadelic, Вы писали:

P>>Спасибо большое! Конечно не всё понял, но спасибо! Про сериализацию почитал на МСДН, теперь хоть знаю что это такое, но в суть не очень вник, инфы было мало, а читать форум мне пока ещё сложно (не тот уровень знаний).

P>>Не знаю, что такое POD-тип, но у меня students это простой класс.

К>Гугл в помощь.
К>Если коротко, это такой тип, объекты которого можно копировать побайтово. Plain Old Data — "старые добрые простые данные".
К>

P>>Хочу задать парочку вопросов:
P>>1) что такое size_t ?

К>Стандартный тип для представления размеров данных.
К>Аналог unsigned int, грубо говоря. (Тонкости возникают на 64-битных платформах LLP64 и LP64, где sizeof(int)=4, sizeof(size_t)=8).

P>>2) out.write((const char*)&count, sizeof(count)); // сохраняем количество
P>> зачем нам сохранять количество элементов и можно ли написать это одной строкой?

К>Затем, что мы же должны оставить потомкам сведения: сколько элементов в массиве.
К>У нас есть 3 стратегии: префиксная, инфиксная, суффиксная.
К>Префиксная — записать "сколько", а потом элементы.
К>Суффиксная — записать элементы и в конце особый завершающий элемент. Например, студента с пустым именем.
К>Инфиксная — записать последовательность, в которой чередуются маркеры (продолжение/конец) и элементы: что-то вроде "+", элемент, "+", элемент, "+", элемент, "-".

К>Соответственно, чтение
К>Префиксная — прочитать "сколько", затем прочитать столько элементов подряд.
К>Суффиксная — читать элементы поштучно и проверять, не является ли очередной признаком конца.
К>Инфиксная — читать маркеры и элементы поштучно; когда прочитан маркер конца, не пытаться прочесть следующий элемент (его там нет).

P>>3) зачем читать количество? in.read((char*)&count, sizeof(count)); // читаем количество

К>Чтобы узнать, сколько элементов следует за ним в файле.
К>Только в том случае, если размер элемента в файле постоянный, и ничего иного в файле нет, — можно взять размер файла и поделить на размер элемента.

P>>4) MasSt.resize(count); // резервируем
P>> резервируем. кол-во элементов, но зачем резервируем, куда и что вообще это значит?)

К>Выделяем память под элементы. Создаём массив.
К>И в этот массив будем читать файл.

К>Думаю, есть смысл сперва прочитать про vector и т.п., а только потом уже бросаться кодить.
К>Иначе будешь ловить один access violation за другим.

Да вы не думайте, что я на форум лезу, а читать мне лень, всё я читаю, но из книг бывает невозможно почерпнуть всё. Может книги у меня не те (Шилдт, Либерти, Дейтлы). Спасибо больше за помощь! Я студент, я только учусь)

Здравствуйте, Psihadelic, Вы писали:

К>>Думаю, есть смысл сперва прочитать про vector и т.п., а только потом уже бросаться кодить.
К>>Иначе будешь ловить один access violation за другим.

P>Да вы не думайте, что я на форум лезу, а читать мне лень, всё я читаю, но из книг бывает невозможно почерпнуть всё. Может книги у меня не те (Шилдт, Либерти, Дейтлы). Спасибо больше за помощь! Я студент, я только учусь)

Я очень хорошо понимаю. Просто на форуме рассматриваются частные вопросы, а в книгах есть возможность получить связную картину. Про сериализацию, про устройство контейнеров, про "модели" объектов (Default Constructible, Copy Constructible, Assignable и т.п.) — это вопрос даже не одной лекции. А это всё — базовые вопросы, к которым мы подступились в этой дискуссии.

Что касается книг, то Шилдт — скорее всего, "не та" книга. Его уже столько раз пропесочивали и за очепятки, и за смысловые ошибки.
Дейтелы. затруднюсь сказать. Читал очень давно, и это была лучшая книга на тот момент.
Вот неплохо бы почитать Герба Саттера. "Эффективная" серия по С++.
Если хватит сил и понимания, то — книги Страуструпа (автор языка) и Степанова (автор STL). Хотя, скорее, это на перспективу.
Чорт! Тут можно вообще учебный план выстраивать.

Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Psihadelic, Вы писали:

К>>>Думаю, есть смысл сперва прочитать про vector и т.п., а только потом уже бросаться кодить.
К>>>Иначе будешь ловить один access violation за другим.

P>>Да вы не думайте, что я на форум лезу, а читать мне лень, всё я читаю, но из книг бывает невозможно почерпнуть всё. Может книги у меня не те (Шилдт, Либерти, Дейтлы). Спасибо больше за помощь! Я студент, я только учусь)

К>Я очень хорошо понимаю. Просто на форуме рассматриваются частные вопросы, а в книгах есть возможность получить связную картину. Про сериализацию, про устройство контейнеров, про "модели" объектов (Default Constructible, Copy Constructible, Assignable и т.п.) — это вопрос даже не одной лекции. А это всё — базовые вопросы, к которым мы подступились в этой дискуссии.

К>Что касается книг, то Шилдт — скорее всего, "не та" книга. Его уже столько раз пропесочивали и за очепятки, и за смысловые ошибки.
К>Дейтелы. затруднюсь сказать. Читал очень давно, и это была лучшая книга на тот момент.
К>Вот неплохо бы почитать Герба Саттера. "Эффективная" серия по С++.
К>Если хватит сил и понимания, то — книги Страуструпа (автор языка) и Степанова (автор STL). Хотя, скорее, это на перспективу.
К>Чорт! Тут можно вообще учебный план выстраивать.

Спасибо большое за то, что посоветовали книги! Герба Саттера. "Эффективная" серия по С++ я не нашёл, но скачал другую его книгу, очень хорошая и интересная, но о векторах я там не нашёл.

Пока код добавления в файл и чтения из файла, подпишу где выскакивает ошибка, а ошибка следующая: Expression:: vector subscript out of range
For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts


Добавление в файл:

Чтение из файла:

Ошибку выдаёт лишь в том случае, если читать сразу после запуска программы, если же после запуска выполнить добавление в файл, и не закрывая читать, то оно работает, но не так, как нужно (читает какую-то фигню, логики в том чтении не вижу, может прочитать весь файл, а в следующий раз только половину).

Здравствуйте, Psihadelic, Вы писали:

P>Чтение из файла:

P>

P>Ошибку выдаёт лишь в том случае, если читать сразу после запуска программы, если же после запуска выполнить добавление в файл, и не закрывая читать, то оно работает, но не так, как нужно (читает какую-то фигню, логики в том чтении не вижу, может прочитать весь файл, а в следующий раз только половину).

Здравствуйте, Psihadelic, Вы писали:

P>Спасибо большое за то, что посоветовали книги! Герба Саттера. "Эффективная" серия по С++ я не нашёл, но скачал другую его книгу, очень хорошая и интересная, но о векторах я там не нашёл.

Для чего в мире есть дебаггер, э?

P>Добавление в файл:
P>[ccode]
P> ofstream out("test", ios::app | ios::binary | ios::out);
P> if(!out)
P> <
P> cout << "не удаётся открыть заданый файл" << endl;
return; // <-- иначе мы поедем дальше с неоткрытым файлом
P> >
P> students _obj; // студенты это класс, там методов нет, только переменные
P> init(_obj); // инициализация объекта
P> MasSt.push_back(_obj); // добавляю в свой вектор объект студентов, а далее по тому, что мне посоветовали на форуме:
P> int count = MasSt.size();
P> out.write((const char*)&count, sizeof(count));
P> out.write((char*) &MasSt[0], count * sizeof (students));
P> out.close();
P>[/code]

P>Чтение из файла:

P>

P>Ошибку выдаёт лишь в том случае, если читать сразу после запуска программы, если же после запуска выполнить добавление в файл, и не закрывая читать, то оно работает, но не так, как нужно (читает какую-то фигню, логики в том чтении не вижу, может прочитать весь файл, а в следующий раз только половину).

vector (он же массив vector , полностью (вместе с пространств. имён, где он определён) std::vector , транслит. вектор) — шаблонный класс контейнера последовательности, представляющий массив, размер которого может динамически изменяться. Официальная замена в C++ стандартному динамическому массиву C.

Содержание

Особенности

Память для вектора выделяется динамически, что можно сделать и вручную с помощью оператора new .

Рекомендации

Разработчики языка C++ рекомендуют в использовать именно vector вместо ручного выделения памяти для обычного массива. Это позволяет избежать утечек памяти и облегчает работу программисту.

В C и C++ имеются некоторые серьёзные неудобства при работе с обычными массивами, поэтому при работе с C++ чаще всего используют именно массивы типа vector как базовые.

Заголовочные файлы

Для работы со стандартными для C++ векторами надо обязательно подключить заголовочный файл «vector» (без Си суффикса/расширения «.h», т.к. это заголовочный файл сугубо C++, т.е. пишется просто <vector> ):

Примеры

Декларация и инициализация

  • Создание/определение вектора и задание его значений
Пустые именованные вектора

Пустой именованный вектор. Вектор с неопределенным размером из элементов типа float :

или с явным вызовом конструктора без параметров:

Пустые и непустые безымянные вектора

Пустой безымянный вектор:

Непустой/заполненный безымянный вектор:

Создание и задание вектора

Вектор типа int из заданных элементов:

Инициализация вектора подобно массивам:

Указание размера и авто-заполнение

Вектор из 5 пустых элементов типа int , т.е. вектор типа int размером в 5 элем. со знач. 0, что явл. знач. по-умолч. для типа int :
В файле основного текста программы:

В заголовочн. файле:

Вектор, состоящий из 8 элементов типа int , по-умолч. все элементы заполняются числом 5:
В файле основного текста программы:

В заголовочн. файле:

Автоматическое создание и заполнение из других векторов и массивов

Инициализация вектора из массива. Результирующий вектор будет аналогом массива, т.е. будет такой же длинны/размера и содержать все элементы массива в том же порядке:

Инициализация вектора из другого вектора:

Инициализация всех элементов определенным значением с помощью функции заливки std::fill (необходимо подключение хедера «algorithm»):

Копирование вектора. Создание одного вектора на основе другого. Создание вектора и заполнение его другим, т.е. элементами др. вектора:

Динамически создаваемый находящийся в управляемой куче вектор

Создание указателя на динамически создаваемый находящийся в управляемой куче вектор:

Динамическое создание в управляемой куче пустого вектора и указателя на него:

Декларация и дефинация

Дефинация

Задать 3 элемента, каждый имеет значение 5:

Добавление

Управление элементами вектора

Добавление/вставка нового элемента в конец вектора с помощью метода push_back :

Вставка нового элемента в начало (остальные элементы сдвигаются):

Удаление элемента из начала (остальные элементы сдвигаются):

Перебор элементов вектора

Стандартный перебор элементов вектора с помощью цикла for :

Перебор элементов вектора с помощью цикла foreach :

Перебор элементов вектора с помощью итератора:

Стандартный перебор элементов динамически создаваемого находящегося в управляемой куче вектора через указатель на него с помощью цикла for :

Разное поведение uniform-инициализации

  • Различное поведение uniform-инициализации вектора в зависимости от типа файла
  • Различное поведение uniform-инициализации вектора в зависимости от контекста

Поведение uniform-инициализации контейнеров-векторов различается в зависимости от контекста, т.е. от того, где это написано - в описании сложного/составного типа данных (класса или структуры), что обычно делается в заголовочн. файле (.h), или во всём остальном, что обычно пишется в файле основного текста программы (.cpp).

СтейтментЧто будет, если это написано в(о)
описании сост. типа дан. (класса/структуры)всём остальном
std::vector<int> num; Создаст 7 пустых ячеек, т.е. со знач. по-умолчанию для типа (для int это 0 ). Создаст 1 ячейку со знач. 7, т.е. просто добавит 7 в массив.
std::vector<int> num; Создаст 7 ячеек со значением 5. Создаст 2 ячейки со знач. 7 и 5, т.е. просто добавит 7 и 5 в массив.
std::vector<int> num; Выдаст ошибку о том, что к классе-шаблоне vector нет функции, принимающей столько аргументов. Создаст 3 ячейки со знач. 7, 5 и 9, т.е. просто добавит 7, 5 и 9 в массив.

Такое поведение имеет место быть, по крайней мере, в стандарте C++11 в IDE Visual Studio 2013.

Операторы

Операторы класса vector :

  • [] — доступ к элементам вектора. Для вектора можно использовать оператор «квадратные скобки», также, как и для обычных массивов.

Методы

Методы класса vector :

  • vector() — конструктор класса vector. Принимает от 0 до 3 параметров.
  • push_back() — добавление нового элемента в конец вектора
  • size() — количество элементов
  • pop_back() — удалить последний элемент
  • clear() — удалить все элементы вектора
  • empty() — проверить вектор на пустоту
  • insert() — вставка нового элемента
  • erase — удаляет из вектора один элемент, либо диапазон элементов.
  • resize — изменяет размер контейнера, чтобы он содержал указанное кол-во элементов, когда уже задан какой-либо размер.
  • assign — присваивает вектору новое содержимое, заменяя его текущее содержимое и соответствующим образом изменяя его размер.

Отличия от массивов

Несмотря на то, что вектора полностью покрывают функционал массивов, всё же у массивов есть некоторые существенные отличия, что могут быть расценены как их достоинства перед векторами.

Указание размеров в заголовочных файлах

В заголовочных файлах и массивы и вектора нельзя инициализировать (задавать знач. при декларации) и дефинировать (задавать знач. после декларации) какими-либо значениями. Но, массивам можно указать/задавать размер при их декларации в заголовочных файлах, а векторам - нет. Т.е., в отличии от обычных массивов, при декларации векторов в заголовочных файлах никак нельзя указать/задать их размер. Однако uniform-инициализация, что ведёт себя по-разному в зависимости от типа файла, позволяет задать размер вектора при декларации в заголовочн. файлах.

Примеры

Для массива можно задать размер при декларации в заголовоч. файле:

Для вектора так сделать нельзя:

В этом случ., напр., в IDE Visual Studio IntelliSense будет подчёркивать красным число, что указывает размер вектора, и говорить, что тут требуется спецификатор типа.

С помощью uniform-инициализации можно задавать размер векторов при декларации их в заголовочн. файлах:

В отличие от std::array, который недалеко отходит от базового функционала обычных фиксированных массивов, std::vector идет в комплекте с дополнительными возможностями, которые делают его одним из самых полезных и универсальных инструментов в языке C++.

Векторы

// Нет необходимости указывать длину при инициализации std :: vector < int > array2 = < 10 , 8 , 6 , 4 , 2 , 1 >; // используется список инициализаторов для инициализации массива std :: vector < int > array3 < 10 , 8 , 6 , 4 , 2 , 1 >; // используется uniform-инициализация для инициализации массива (начиная с C++11)

Обратите внимание, что в неинициализированном, что в инициализированном случаях вам не нужно явно указывать длину массивов. Это связано с тем, что std::vector динамически выделяет память для своего содержимого по запросу.

Подобно std::array, доступ к элементам массива может выполняться как через оператор [] (который не выполняет проверку диапазона), так и через функцию at() (которая выполняет проверку диапазона):

В любом случае, если вы будете запрашивать элемент, который находится вне диапазона array , длина вектора автоматически изменяться не будет. Начиная с C++11, вы также можете присваивать значения для std::vector, используя список инициализаторов:

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

Нет утечкам памяти!

Когда переменная-вектор выходит из области видимости, то она автоматически освобождает память, которую контролировала (занимала). Это не только удобно (так как вам не нужно это делать вручную), но также помогает предотвратить утечки памяти. Рассмотрим следующий фрагмент:

delete [ ] array ; // если value == true, то этот стейтмент никогда не выполнится

Если переменной value присвоить значение true , то array никогда не будет удален, память никогда не будет освобождена и произойдет утечка памяти.

Однако, если бы array был вектором, то подобное никогда бы и не произошло, так как память освобождалась бы автоматически при выходе array из области видимости (независимо от того, выйдет ли функция раньше из области видимости или нет). Именно из-за этого использование std::vector является более безопасным, чем динамическое выделение памяти через оператор new.

Длина векторов

В отличие от стандартных динамических массивов, которые не знают свою длину, std::vector свою длину запоминает. Чтобы её узнать, нужно использовать функцию size():

The length is: 7

Изменить длину стандартного динамически выделенного массива довольно проблематично и сложно. Изменить длину std::vector так же просто, как вызвать функцию resize():

The length is: 7
0 1 2 0 0 0 0

Здесь есть две вещи, на которые следует обратить внимание. Во-первых, когда мы изменили длину array , существующие значения элементов сохранились! Во-вторых, новые элементы были инициализированы значением по умолчанию в соответствие с определенным типом данных (значением 0 для типа int).

Длину вектора также можно изменить и в обратную сторону (обрезать):

The length is: 4
0 1 4 7

Изменение длины вектора является затратной операцией, поэтому вы должны стремиться минимизировать количество подобных выполняемых операций.

Заключение

Это вводная статья, предназначенная для ознакомления с основами std::vector. На следующих уроках мы детально рассмотрим std::vector, в том числе и разницу между длиной и ёмкостью вектора, и то, как в std::vector выполняется выделение памяти.

Поскольку переменные типа std::vector могут сами управлять выделенной себе памятью (что помогает предотвратить утечку памяти), отслеживают свою длину и легко её изменяют, то рекомендуется использовать std::vector вместо стандартных динамических массивов.

(386 оценок, среднее: 4,88 из 5)

Урок №94. Введение в std::array

Комментариев: 17

Как использовать вектор (vecto) в C++

Программирование и разработка

Как использовать вектор (vecto) в C++

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

C ++ имеет множество библиотек, все из которых составляют стандартную библиотеку C ++. Одна из этих библиотек — это библиотека контейнеров. Контейнер — это набор объектов, и с этой коллекцией можно выполнять определенные операции. Контейнеры C ++ можно сгруппировать в два набора: контейнеры последовательности и ассоциативные контейнеры. Контейнеры последовательности — это vector, array (не тот массив, который обсуждался ранее), deque, forward_list и list. Это разные коллекции (структуры данных, подобные массивам), и каждая предлагает различные компромиссы.

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

Если задача включает частые вставки и удаления в середине последовательности, следует использовать список или forward_list. Если задача включает частые вставки и удаления в начале или конце последовательности, следует использовать двухстороннюю очередь. Вектор следует использовать, когда такого рода операции не требуются.

В этой статье показано, как использовать вектор C ++. Для понимания этой статьи вам потребуются некоторые знания указателей, ссылок и массивов C ++.

Класс и объекты

Класс — это набор переменных и функций, которые работают вместе, где переменным не присвоены значения. Когда переменным присваиваются значения, класс становится объектом. Различные значения, присвоенные одному и тому же классу, приводят к разным объектам; то есть разные объекты могут принадлежать к одному классу, но иметь разные значения. Создание объекта из класса также известно как создание экземпляра объекта.

Термин вектор описывает класс. Объект, созданный из вектора, имеет имя, выбранное программистом.

Функция, принадлежащая классу, необходима для создания экземпляра объекта из класса. В C ++ эта функция имеет то же имя, что и имя класса. Различные объекты, созданные (экземпляры) из класса, имеют разные имена, данные каждому из них программистом.

Создание объекта из класса означает создание объекта; это также означает создание экземпляра объекта.

Класс Vector

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

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

Создание экземпляра вектора

Выше объявление массива с именем «foo» и количеством элементов «10». Это массив целых чисел. Объявление вектора аналогично. Для вектора количество элементов не является обязательным, поскольку длина вектора может увеличиваться или уменьшаться.

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

Здесь вектор принадлежит специальной функции-конструктору. Тип данных, которые будет содержать вектор, — это «int» в угловых скобках. Термин «vtr» — это имя, выбранное программистом для вектора. Наконец, «8» в скобках — это ориентировочное количество целых чисел, которые будет иметь вектор.

Термин «std» означает стандартное пространство имен. В этом контексте после этого термина должно стоять двойное двоеточие. Кто угодно может написать свою собственную библиотеку векторных классов и использовать ее. Однако в C ++ уже есть стандартная библиотека со стандартными именами, включая «вектор». Чтобы использовать стандартное имя, стандартному имени должен предшествовать std . Чтобы не вводить std :: каждый раз в программе для стандартного имени, файл программы может запускаться следующим образом:

Перегрузка функции

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

Построение вектора

Построение вектора означает инстанцирование (создание) векторного объекта. Функция-конструктор перегружается следующим образом:

vector <T> name

Это создает вектор нулевой длины и набирает «T.» Следующая инструкция создает вектор нулевой длины типа «float» с именем «vtr»:

vector <T> name (n)

Это создает вектор с n элементами типа «T.» Утверждение для этого вектора с четырьмя элементами с плавающей запятой выглядит следующим образом:

vector <T> name (n, t)

Это создает вектор из n элементов, инициализированных значением t. Следующий оператор создает вектор из 5 элементов, каждый из которых имеет значение 3,4:

Конструирование с инициализацией

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

Обратите внимание, что сразу после имени объекта скобок нет. Круглые скобки, используемые сразу после имени объекта, должны содержать список инициализаторов, как показано ниже:

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

Это конструктор копирования. Он создает вектор V2 как копию вектора V1. Следующий код иллюстрирует это:

Назначение вектора во время Construction

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

Второй оператор эквивалентен:

const Vector

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

В этом векторном типе ни один элемент не может быть добавлен или удален. Более того, никакое значение не может быть изменено.

Конструирование с помощью Iterator

Шаблон предоставляет общее представление для типа данных. Итератор обеспечивает общее представление сканирования значений контейнера. Синтаксис для создания вектора с итератором следующий:

template < class InputIterator >
vector ( InputIterator first , InputIterator last , const Allocator & = Allocator ( ) ) ;

Это создает вектор для диапазона [первый, последний) с использованием указанного распределителя, который будет обсуждаться позже в этой статье.

Уничтожение вектора

Чтобы уничтожить вектор, просто позвольте ему выйти из области видимости, и уничтожение будет выполнено автоматически.

Емкость вектора

size_type capacity () const noexcept

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

reserve(n)

Пространство памяти не всегда доступно. Дополнительное место можно зарезервировать заранее. Рассмотрим следующий фрагмент кода:

Результатом будет 6. Таким образом, зарезервировано дополнительное пространство 6 — 4 = 2 элемента. Функция возвращает void.

size () const noexcept

Это возвращает количество элементов в векторе. Следующий код иллюстрирует эту функцию:

shrink_to_fit()

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

На выходе будет 4, а не 6. Функция возвращает void.

resize(sz), resize(sz,c)

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

New size of vtr1: 2
vtr2: 1.1 2.2 8.8 8.8

Функции возвращают void.

empty() const noexcept

Эта функция возвращает 1 для истины, если в векторе нет элементов, и 0 для false, если вектор пуст. Если вектор имеет 4 местоположения для определенного типа данных, например, с плавающей запятой, без какого-либо значения с плавающей запятой, то этот вектор не является пустым. Следующий код иллюстрирует это:

Доступ к элементу вектора

Вектор может быть подписан (проиндексирован) как массив. Подсчет индекса начинается с нуля.

vectorName[i]

Операция «vectorName [i]» возвращает ссылку на элемент в i- м индексе вектора. Следующий код выводит 3.3 для указанного выше вектора:

vectorName [i] const

Операция «vectorName [i] const» выполняется вместо «vectorName [i]», когда вектор является постоянным вектором. Эта операция используется в следующем коде:

Выражение возвращает постоянную ссылку на i- й элемент вектора.

Присвоение значения с помощью нижнего индекса

Значение может быть присвоено непостоянному вектору следующим образом:

На выходе получается 8.8.

vectorName.at (i)

«VectorName.at (i)» похож на «vectorName [i]», но «vectorName.at (i)» более надежен. Следующий код показывает, как следует использовать этот вектор:

vectorName.at (i) const

«VectorName.at (i) const» похоже на «vectorName [i] const», но «vectorName.at (i) const» более надежен. «VectorName.at (i) const» выполняется вместо «vectorName.at (i)», когда вектор является постоянным вектором. Этот вектор используется в следующем коде:

Присвоение значения с помощью функции at ()

Значение может быть присвоено непостоянному вектору с помощью функции at () следующим образом:

На выходе получается 8.8.

Проблема с подпрограммами

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

front()

Это возвращает ссылку на первый элемент вектора без удаления элемента. Результатом следующего кода является 1.1.

Элемент не удаляется из вектора.

front() const

Когда конструкции вектора предшествует const, выражение «front () const» выполняется вместо «front ()». Это используется в следующем коде:

Возвращается постоянная ссылка. Элемент не удаляется из вектора.

back()

Это возвращает ссылку на последний элемент вектора без удаления элемента. Вывод следующего кода — 4.4.

back() const

Когда конструкции вектора предшествует const, выражение «back () const» выполняется вместо «back ()». Это используется в следующем коде:

Возвращается постоянная ссылка. Элемент не удаляется из вектора.

Доступ к векторным данным

data() noexcept; data() const noexcept;

Подробнее об этом будет рассказано позже в статье.

Возвращение итераторов и вектора

Итератор похож на указатель, но имеет больше функций, чем указатель.

begin() noexcept

Возвращает итератор, указывающий на первый элемент вектора, как в следующем сегменте кода:

На выходе получается 1.1. Обратите внимание, что объявление, которое получает итератор, было объявлено. Итератор разыменовывается в возвращаемом выражении для получения значения так же, как разыменование указателя.

begin () const noexcept;

Возвращает итератор, указывающий на первый элемент вектора. Когда конструкции вектора предшествует константа, выражение «begin () const» выполняется вместо «begin ()». При этом условии соответствующий элемент в векторе не может быть изменен. Это используется в следующем коде:

На выходе получается 1.1. Обратите внимание, что на этот раз был использован «const_iterator» вместо простого «итератора» для получения возвращенного итератора.

end() noexcept

Возвращает итератор, который указывает сразу за последним элементом вектора. Рассмотрим следующий фрагмент кода:

Результатом будет 0, что бессмысленно, поскольку за последним элементом нет конкретного элемента.

end() const noexcept

Возвращает итератор, который указывает сразу за последним элементом вектора. Когда конструкции вектора предшествует «const», выражение «end () const» выполняется вместо «end ()». Рассмотрим следующий фрагмент кода:

Результатом будет 0. Обратите внимание, что на этот раз был использован «const_iterator» вместо простого «итератора» для получения возвращенного итератора.

Обратная итерация

Возможно иметь итератор, который выполняет итерацию от конца до самого первого элемента.

rbegin() noexcept

Возвращает итератор, указывающий на последний элемент вектора, как в следующем сегменте кода:

Обратите внимание, что объявлено объявление, получающее обратный итератор. Итератор разыменовывается в возвращаемом выражении для получения значения так же, как разыменование указателя.

rbegin () const noexcept;

Возвращает итератор, указывающий на последний элемент вектора. Когда конструкции вектора предшествует «const», выражение «rbegin () const» выполняется вместо «rbegin ()». При этом условии соответствующий элемент в векторе не может быть изменен. Эта функция используется в следующем коде:

Обратите внимание, что на этот раз был использован const_reverse_iterator вместо только reverse_iterator для получения возвращенного итератора.

rend () noexcept

Возвращает итератор, который указывает непосредственно перед первым элементом вектора. Рассмотрим следующий фрагмент кода:

Результатом будет 0, что не имеет смысла, поскольку непосредственно перед первым элементом нет конкретного элемента.

rend () const noexcept

Возвращает итератор, который указывает непосредственно перед первым элементом вектора. Когда конструкции вектора предшествует «const», выражение «rend () const» выполняется вместо «rend ()». Рассмотрим следующий фрагмент кода:

Обратите внимание, что на этот раз был использован const_reverse_iterator вместо только reverse_iterator для получения возвращенного итератора.

Векторные модификаторы

Модификатор, изменяющий вектор, может принимать или возвращать итератор.

a.emplace (p, args)

insert(iteratorPosition, value)

Вставляет копию значения в позицию итератора вектора. Возвращает итератор (позицию) в векторе, куда была помещена копия. Следующий код показывает, где было размещено значение:

Обратите внимание, что итератор был расширен (увеличен) точно так же, как указатель.

Также можно вставить список инициализаторов, как показано в следующем коде:

Вывод: 20 25 28 30.

erase(position)

Удаляет элемент в позиции, на которую указывает итератор, затем возвращает позицию итератора. Следующий код иллюстрирует это:

push_back(t), push_back(rv)

Используется для добавления одного элемента в конец вектора. Используйте push_back (t) следующим образом:

pop_back()

Удаляет последний элемент, не возвращая его. Размер вектора уменьшается на 1. Следующий код иллюстрирует это:

a.swap(b)

Два вектора можно поменять местами, как показано в следующем фрагменте кода:

Обратите внимание, что длина вектора при необходимости увеличивается. Кроме того, значения, для которых не было замен, заменяются некоторым значением по умолчанию.

clear()

Удаляет все элементы из вектора, как показано в следующем сегменте кода:

Операторы равенства и отношения для векторов

The == Operator

Возвращает 1 для истины, если два вектора имеют одинаковый размер и соответствующие элементы равны; в противном случае он возвращает 0 для ложного. Например:

The != Operator

Возвращает 1 для истины, если два вектора не имеют одинакового размера и / или соответствующие элементы не равны; в противном случае он возвращает 0 для ложного. Например:

The < Operator

Возвращает 1 для истины, если первый вектор является начальным подмножеством второго вектора, причем элементы двух равных частей одинаковы и находятся в одном порядке. Если оба вектора имеют одинаковый размер и движутся слева направо, и в первом векторе встречается элемент, который меньше соответствующего элемента во втором векторе, то все равно будет возвращено 1. В противном случае возвращается 0 для false. Например:

Вывод 1. <не включает случай, когда размер и порядок совпадают.

The > Operator

The <= Operator

The >= Operator

Возвращает! (U <= V), где U — первый вектор, а V — второй вектор, согласно приведенным выше определениям.

Заключение

Вектор — это пример контейнера последовательности. Вектор является «лучшей» формой обычного массива и создается из класса. У векторов есть методы, которые классифицируются по следующим категориям: построение и присвоение, емкость, доступ к элементам, доступ к данным, итераторы, модификаторы и числовые перегруженные операторы.

Существуют и другие контейнеры последовательности, называемые списком, forward_list и массивом. Если задача включает частые вставки и удаления в середине последовательности, следует использовать список или forward_list. Если задача включает частые вставки и удаления в начале или конце последовательности, следует использовать двухстороннюю очередь. Итак, векторы следует использовать только тогда, когда такого рода операции не важны.е важны.

Читайте также: