Чтение онлайн

на главную - закладки

Жанры

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

 try {

intVec.at(300) = 2;

 } catch(out_of_range& e) {

cerr << "out_of_range: " << e.what << endl;

 }

}

Обсуждение

В целом, если требуется использовать массив, вместо него следует использовать

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

Если вы не знакомы с контейнерами, поставляющимися в составе стандартной библиотеки, или не сталкивались с использованием шаблонов классов (и их написанием), то объявление

vector
в примере 6.1 требует некоторых пояснений. Объявление
vector
имеет следующий вид.

vector<typename Value, // Тип элемента, который будет храниться в этом векторе

 typename Allocator = allocator<Value> > // используемый распределитель (allocator)

// памяти

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

Если вы хотите, чтобы

vector
хранил элементы типа
int
, объявите его, как в этом примере.

vector<int> intVec;

А если вам требуется, чтобы он хранил строки, просто измените тип аргумента

vector
.

vector<string> strVec;

vector
может содержать любой тип С++, который поддерживает конструктор копирования и присвоение.

Следующее, что логически требуется сделать после создания экземпляра

vector
, — это что-либо поместить в него. В конец вектора элементы добавляются с помощью
push_back
.

intVec.push_back(3);

intVec.push_back(9);

intVec.push_back(6);

Это примерно эквивалентно добавлению элементов 0, 1 и 2 в массив. Это «примерно» эквивалентно потому, что, конечно,

push_back
— это метод, который возвращает
void
и помещает свой аргумент в конец вектора.
operator[]
возвращает ссылку на область памяти, на которую указывает индекс массива,
push_back
гарантирует, что во внутреннем буфере
vector
окажется достаточно места для добавления аргумента. Если место есть, то он добавляется в следующий неиспользуемый индекс, а если нет, то буфер увеличивается с помощью зависящего от реализации алгоритма, а затем в него добавляется аргумент

Также с помощью метода

insert
можно вставить элементы в середину вектора, хотя этого следует избегать из-за линейно возрастающей сложности этой операции. За более подробным обсуждением проблем производительности и их решения при использовании
vector
обратитесь к рецепту 6.2. Чтобы вставить элемент, получите итератор на точку, куда требуется его вставить (обсуждение итераторов приводится в рецепте 7.1).

string s = "Marines";

vector<string>::iterator p = find(strVec.begin

strVec.end, s);

if (s != strVec.end) //
Вставляет s непосредственно перед элементом,

 strVec.insert(p, s); // на который указывает p

Перегруженные версии

insert
позволяют вставлять в вектор n копий объекта, а также вставлять целый диапазон другой последовательности (эта последовательность может быть другим
vector
, массивом,
list
и т.п.).

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

assign
. Вектору можно присвоить диапазон значений или n копий одного и того же объекта, как здесь.

string sarr[3] = {"Ernie", "Bert", "Elmo"};

string s = "Oscar";

strVec.assign(&sarr[0], &sarr[3]); // Присвоить эту последовательность

strVec.assign(50, s); // Присвоить 50 копий s

Если новая последовательность окажется больше, чем имеющийся размер буфера

vector
, то
assign
изменит размер буфера так, чтобы разместить в нем всю новую последовательность.

После того как данные помещены в

vector
, имеется несколько способов получения их назад. Вероятно, наиболее интуитивным является
operator[]
, который возвращает ссылку или
const
– ссылку в зависимости от того, является ли вектор
const
или нет, на элемент по указанному индексу. В этом отношении он ведет себя почти как массив:

for (int i = 0; i < intVec.size; ++i) {

 std::cout << "intVec[" << i << "] = "

<< intVec[i] << '\n'; // rvalue

}

intVec[2] = 32; // lvalue

operator[]
также ведет себя как массив в том, что при использовании индекса, который больше, чем индекс последнего элемента
vector
, результат не определен, что обычно означает, что будут повреждены данные программы или она обрушится. Избежать этого можно, запросив число элементов, содержащихся в
vector
, с помощью
size
. Однако использованию
operator[]
следует предпочитать итераторы, так как их использование является стандартным для перебора элементов любого стандартного контейнера.

for (vector<string>::iterator p = strVec.begin;

 p != strVec.end; ++p) {

 std::cout << *p << '\n';

}

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

operator[]
вы ограничиваете себя использованием только тех контейнеров, которые поддерживают произвольный доступ. Первый подход позволяет алгоритмам стандартной библиотеки из
<algorithm>
одинаково работать со стандартными контейнерами (и другими типами, ведущими себя, как они).

Поделиться:
Популярные книги

Я тебя не предавал

Бигси Анна
2. Ворон
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Я тебя не предавал

Матабар. II

Клеванский Кирилл Сергеевич
2. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар. II

Владеющий

Злобин Михаил
2. Пророк Дьявола
Фантастика:
фэнтези
8.50
рейтинг книги
Владеющий

Совершенный: Призрак

Vector
2. Совершенный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Совершенный: Призрак

По осколкам твоего сердца

Джейн Анна
2. Хулиган и новенькая
Любовные романы:
современные любовные романы
5.56
рейтинг книги
По осколкам твоего сердца

Герцогиня в ссылке

Нова Юлия
2. Магия стихий
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Герцогиня в ссылке

Метатель

Тарасов Ник
1. Метатель
Фантастика:
боевая фантастика
попаданцы
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Метатель

На изломе чувств

Юнина Наталья
Любовные романы:
современные любовные романы
6.83
рейтинг книги
На изломе чувств

Магия чистых душ

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.40
рейтинг книги
Магия чистых душ

(Не)нужная жена дракона

Углицкая Алина
5. Хроники Драконьей империи
Любовные романы:
любовно-фантастические романы
6.89
рейтинг книги
(Не)нужная жена дракона

Часовая битва

Щерба Наталья Васильевна
6. Часодеи
Детские:
детская фантастика
9.38
рейтинг книги
Часовая битва

Новый Рал 2

Северный Лис
2. Рал!
Фантастика:
фэнтези
7.62
рейтинг книги
Новый Рал 2

Боярышня Дуняша 2

Меллер Юлия Викторовна
2. Боярышня
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Боярышня Дуняша 2

Город Богов

Парсиев Дмитрий
1. Профсоюз водителей грузовых драконов
Фантастика:
юмористическая фантастика
детективная фантастика
попаданцы
5.00
рейтинг книги
Город Богов