|
Программирование >> Немодифицирующие последовательные алгоритмы
Initial sequence L2: 15 35 After Ll.merge(L2): 10 15 20 30 35 Последняя строчка вывода показывает новый список II, в то время как 11 становится пустым. Хотя имя функции merge совпадает с именем алгоритма merge, последний работает по-другому (см. раздел 1.7). 3.6. Векторы векторов До сих пор в наших примерах излюбленным типом был vector<int>. Вполне очевидно, что мы можем заменить int на другой тип и использовать vector<double>, vector<char> и т. п. А вправе ли мы использовать более сложный тип, чем int, double и char, между двумя угловыми скобками? Например, можно ли написать vector<vector<int> > А; Да, возможно, как в следующей программе: vecvec.cpp: Вектор векторов. iinclude <iostream> iinclude <vector> using namespace std; int mainO { vector <int>v; V.push back(8); v.push back(9); vector<vector<int> > A; A.push back(v); A.push back(v); A.push back(v); for (int i=0; i<3; i++) { for (int j=0; j<2; j++) cout A[i][j] ; cout endl; return 0; Программа использует вектор A, состоящий из трех элементов, каждый из которых является вектором, содержащим два целых числа 8 и 9. Мы можем считать вектор А двумерным массивом, или матрицей, как показывает вывод этой программы: Следует иметь в виду, что предложенный автором второй вариант реализации двумерного массива с помощью вектора указателей не только менее эффективен по времени выполнения и менее защищен от случайного неправильного выделения/освобождения памяти (см. раздел 3.7), но в случае плотно заполненной матрицы может фактически использовать больше памяти, чем первый вариант, использующий вектор из векторов! В реальных программах на С++ подобных приемов следует избегать. - Прим. переводчика. 8 9 8 9 8 9 Однако такой подход может привести к тому, что нам потребуется больше памяти, чем действительно необходимо. Довольно часто программисты на С и С++ используют вместо двумерных массивов массивы указателей. Точно так же можно использовать вектор указателей, реализованный в следующей программе, вывод которой совпадает с предыдущей: pointers.срр: Вектор указателей, iinclude <iostream> iinclude <vector> using namespace std; typedef vector<int> vecint; int main() { vector<vecint*> A; int a[2] = {8, 9}; A.push back(new vecint(a, a+2)) A.push back(new vecint(a, a+2)) A.push back(new vecint(a, a+2)) for (int i=0; i<3; i++) { for (int j=0; j<2; j++) cout (*A[i])[j] ; cout endl; delete A[0]; delete A[l]; delete A[2]; return 0; Каждый элемент вектора A, A[i] является указателем на вектор из двух элементов целого типа, так что является этим вектором, содержа- щим целые значения, доступ к которым осуществляется с помощью выражения *(/![?])[/]. 3.7. Как избавиться от явного выделения памяти Как было отмечено в разделе 1.14, в сложных программах к частым ошибкам приводит освобождение памяти с помощью/гее или delete. В данных ниже определениях функций нельзя обойтись без использования упомянутых выражений. Если же мы забудем сделать это, возникнет так называемая утечка памяти, то есть динамически вьщеленная память не будет освобождена: void f(int n) { double *a; a = (double*)malloc(n * sizeof(double)); ... Используем a[0], a[n-l]. free(a); Bo избежание утечки памяти либо void f(int n) { double *a; a = new double[n]; Используем a[0], a[n-l]. delete[] a; Bo избежание утечки памяти Нам следует также заботиться о том, чтобы не разместить область памяти более одного раза и, если память была выделена при выполнении какого-либо условия, не пытаться освободить ее без проверки условия. Используя STL, мы можем избежать использования malloc и new, применяя контейнер vector. Преимущество этого подхода заключается в снижении риска неправильного использования/гее или delete. Например, вместо рассмотренной выше функции мы можем написать ♦include <vector> void f(int n) { vector<double> a(n); См. раздел 3.3. Используем a[0], а[п-1]. Освобождение памяти теперь осуществляется деструктором контейнера. Векторы как члены классов Векторы также можно использовать вместо определенных внутри классов массивов, которые размещаются и освобождаются явным образом. Рассмотрим для примера следующий код, использующий явное выделение и освобождение памяти:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |