Перейти к содержимому

Как увеличить динамический массив c

  • автор:

Увеличение динамического массива в С++

Возникла проблемка которая не дает мне спокойствия. Суть такова, есть указатель на целое int *a;Затем выделяем память, а=new int[10]; потом, заполнили его в цикле числами. И тут мне надо еще добавить ячеек в массив а, что бы туда записать числа, можно конечно через временный массив но мне не хотеться. Когда так делаю а=new int[20]; то вся информация что была раньше исчезает. Как увеличить массив без потери данных? Заранее спасибо!
Пример

int *a;
a =new int [10];

a=new int [20];//тут вся информация исчезает

11 ответов

01 ноября 2007 года
1.0K / / 08.01.2007
Используй вектор.

int _tmain(int argc, _TCHAR* argv[])
vector coll;
for(int i = 0;i < 10;++i)
coll.push_back(i);
coll.push_back(10);
coll.push_back(22);
for(int i = 0;i < coll.size();++i)
cout cout return 0;
>

02 ноября 2007 года
68 / / 01.11.2007

m_Valery cпасибо что откликнулся и сразу же вопрос. В vector –е можно использовать структуры(vector), просто я привел простейший пример, а мне надо массив структур увеличивать. Как с этим быть?

02 ноября 2007 года
277 / / 11.10.2006
естественно можно:-)
struct sHosts
string hostname;
string nserver;
string devid;
string fixaddr;
>;
vectorhosts;
02 ноября 2007 года
2.5K / / 14.07.2006

Можно исспользовать любой тип. Главное чтобы для него были определенны оператор присваивания и конструктор копирования.

Ну или можно исспользовать указатель на тип (который сам по себе тип но у него есть оператор присваивания). ))

02 ноября 2007 года
1.1K / / 19.09.2006
Когда так делаю а=new int[20]; то вся информация что была раньше исчезает.

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

// выделяем блок памяти под 10 элементов размером с int (4*10 байт)
int *array = (int*) malloc (10 * sizeof (int));
// изменяем размер блока выделенной памяти
array = (int*) realloc (array, 20 * sizeof (int));
// освобождаем память
free (array)

При увеличении блока, функция может выполнить перемещение данных в бо’льшую область памяти.
Данные функции не обнуляют выделенную память и не вызывают ни конструкторы, ни деструкторы (в отличие от new[] и delete[]) — поэтому их очень сложно использовать для сложных типов..

03 ноября 2007 года
68 / / 01.11.2007
Всем спасибо помогли хорошенько
27 августа 2010 года
2 / / 27.08.2010

Я постоянно работаю с динамическими массивами в Object Pascal и PHP. Вот внезапно возникла необходимость использования языка C++ и пришлось немного почесать голову )). :confused:

Библиотека это конечно хорошо, но почему изменение длины массива не реализовано в стандартной библиотеке. А ведь C++ самый успешный и развивающийся язык программирования.

Учитывая тот факт что в С++ можно объявить массив где угодно в теле алгоритма, то преимущества динамического массива сужаются к двум:
1. можно создавать (суб)подмассивы произвольной длинны (в принципе существенный фактор);
2. тут же удалить массив из памяти после выполнения необходимых операций (не дожидаясь конца функции и т.п.).

А для Object Pascal преимущества динамического массива увеличиваются как минимум на два:
3. не занимает памяти, пока массив не востребован, т.е. не задана длинна (большой бонус, поскольку переменные объявляются только в разделе var и занимают память от начала алгоритма);
4. можно сколь угодно удлинять и укорачивать массив без потери данных в пределах усечения ( пример SetLength(Massiv, 1) ).

Резонные вопросы:
1. может Object Pascal хитрит, т.е. метод SetLength создает второй массив новой длины и копирует данные с первого и переписывает указатель?
2. или забросили и недоделали данную операцию в С++ поскольку была библиотека (бред какой-то)? 😮

Ответы на свои вопросы искал заранее, но нигде ничего не нашел. Может Вы, где что видели или знаете? Заранее благодарен. :rolleyes:

27 августа 2010 года
452 / / 12.08.2009

шаблонный класс vector находится в STL, что расшифровывается как Standart Template Libraty(стандартная библиотека шаблонов).

1. может Object Pascal хитрит, т.е. метод SetLength создает второй массив новой длины и копирует данные с первого и переписывает указатель?

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

2. или забросили и недоделали данную операцию в С++ поскольку была библиотека (бред какой-то)?

C++ — это использование STL для работы с контейнерами.
операции new и delete растут из Си с malloc и free

в vector расширение памяти под хранимые объекты можно производить как явно, так и не явно, так что всё есть в C++

Как увеличить динамический массив c

Кроме отдельных динамических объектов в языке C++ мы можем использовать динамические массивы. Для выделения памяти под динамический массив также используется оператор new , после которого в квадратных скобках указывается, сколько массив будет содержать объектов:

int *numbers ; // динамический массив из 4 чисел // или так // int *numbers = new int[4];

Причем в этом случае оператор new также возвращает указатель на объект типа int — первый элемент в созданном массиве.

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

int *numbers1 >; // массив состоит из чисел 0, 0, 0, 0 int *numbers2 >; // массив состоит из чисел 1, 2, 3, 4 int *numbers3 >; // массив состоит из чисел 1, 2, 0, 0 // аналогичные определения массивов // int *numbers1 = new int[4]<>; // массив состоит из чисел 0, 0, 0, 0 // int *numbers1 = new int[4](); // массив состоит из чисел 0, 0, 0, 0 // int *numbers2 = new int[4]< 1, 2, 3, 4 >; // массив состоит из чисел 1, 2, 3, 4 // int *numbers3 = new int[4]< 1, 2 >; // массив состоит из чисел 1, 2, 0, 0

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

Стоит отметить, что в стандарт С++20 добавлена возможность выведения размера массива, поэтому, если применяется стандарт С++20, то можно не указывать длину массива:

int *numbers >; // массив состоит из чисел 1, 2, 3, 4

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

int *numbers >; // получение элементов через синтаксис массивов std::cout 

Причем для доступа к элементам динамического массива можно использовать как синтаксис массивов ( numbers[0] ), так и операцию разыменования ( *numbers )

Соответственно для перебора такого массива можно использовать различные способы:

unsigned n< 5 >; // размер массива int* p < new int[n] < 1, 2, 3, 4, 5 >>; // используем индексы for (unsigned i<>; i < n; i++) < std::cout std::cout ; i < n; i++) < std::cout std::cout ; q != p + n; q++) < std::cout std::cout 

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

Для удаления динамического массива и освобождения его памяти применяется специальная форма оператора delete :

delete [] указатель_на_динамический_массив;

#include int main() < unsigned n< 5 >; // размер массива int* p < new int[n] < 1, 2, 3, 4, 5 >>; // используем индексы for (unsigned i<>; i < n; i++) < std::cout std::cout

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

delete [] p; p = nullptr; // обнуляем указатель

Многомерные массивы

Также мы можем создавать многомерные динамические массивы. Рассмотрим на примере двухмерных массивов. Что такое по сути двухмерный массив? Это набор массив массивов. Соответственно, чтобы создать динамический двухмерный массив, нам надо создать общий динамический массив указателей, а затем его элементы - вложенные динамические массивы. В общем случае это выглядит так:

#include int main() < unsigned rows = 3; // количество строк unsigned columns = 2; // количество столбцов int** numbers>; // выделяем память под двухмерный массив // выделяем память для вложенных массивов for (unsigned i<>; i < rows; i++) < numbers[i] = new int[columns]<>; > // удаление массивов for (unsigned i<>; i < rows; i++) < delete[] numbers[i]; >delete[] numbers; >

Вначале выделяем память для массива указателей (условно таблицы):

int** numbers>;

Затем в цикле выделяем память для каждого отдельного массива (условно строки таблицы):

numbers[i] = new int[columns]<>;

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

Пример с вводом и выводом данных двухмерного динамического массива:

#include int main() < unsigned rows = 3; // количество строк unsigned columns = 2; // количество столбцов int** numbers>; // выделяем память под двухмерный массив for (unsigned i<>; i < rows; i++) < numbers[i] = new int[columns]<>; > // вводим данные для таблицы rows x columns for (unsigned i<>; i < rows; i++) < std::cout ; j < columns; j++) < std::cout > numbers[i][j]; > > // вывод данных for (unsigned i<>; i < rows; i++) < // выводим данные столбцов i-й строки for (unsigned j<>; j < columns; j++) < std::cout std::cout for (unsigned i<>; i < rows; i++) < delete[] numbers[i]; >delete[] numbers; >

Пример работы программы:

Enter data for 1 row 1 column: 2 2 column: 3 Enter data for 2 row 1 column: 4 2 column: 5 Enter data for 3 row 1 column: 6 2 column: 7 2 3 4 5 6 7

Указатель на массив

От типа int** , который представляет указатель на указатель (pointer-to-pointer) следует отличать ситуацию "указатель на массив" (pointer to array). Например:

#include int main() < unsigned n; // количество строк int (*a)[2] = new int[n][2]; int k<>; // устанавливаем значения for (unsigned i<>; i < n; i++) < // устанавливаем данные для столбцов i-й строки for (unsigned j<>; j < 2; j++) < a[i][j] = ++k; >> // вывод данных for (unsigned i<>; i < n; i++) < // выводим данные столбцов i-й строки for (unsigned j<>; j < 2; j++) < std::cout std::cout // удаляем данные delete[] a; a = nullptr; >

Здесь запись int (*a)[2] представляет указатель на массив из двух элементов типа int. Фактически мы можем работать с этим объектом как с двухмерным массивом (таблицей), только количество столбцов в данном случае фиксировано - 2. И память для такого массива выделяется один раз:

int (*a)[2] = new int[n][2];

То есть в данном случае мы имеем дело с таблице из n строк и 2 столцов. Используя два индекса (для строки и столца), можно обращаться к определенному элементу, установить или получить его значение. Консольный вывод данной программы:

1 2 3 4 5 6

Увеличение размера динамического массива c-style строк

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

2 окт 2017 в 16:54

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Да, в общем-то, все то же самое:

  • Создаете новый массив new char*[sz*2];
  • В него копируете указатели на с-строки из старого массива;
  • Убиваете старый массив;
  • Возвращаете указатель на новый массив.

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

Отслеживать
ответ дан 2 окт 2017 в 16:46
Voidificator Voidificator
1,973 7 7 серебряных знаков 7 7 бронзовых знаков

  • c++
  • c
  • массивы
  • строки
  • динамические-массивы
    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Как увеличить размер массива в C++?

Подскажите пожалуйста примерную идею,как можно увеличить размер массива на с++.
Задача такова,что есть динамический массив,который пользователь заполняет.Далее,нужно написать функцию,которая добавляет элемент к массиву только в том случае,если этот елемент отсутствует. Написал вот такую функцию:

int* addItemToArray(int* array, int size, int newItem) < for (int i = 0; i < size; i++)< if (newItem == *(array + i))< return nullptr; >> int* newArray = new int[size + 1]; for (int i = 0; i < size; i++)< *(newArray+i) == *(array + i); >*(newArray + size + 1) = newItem; return newArray; >

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

int L,I; cout > L; int* lineArray = new int[L]; srand(time(0)); for (int j = 0; j < L; j++)< cout > I; > cout > I; while ((lineArray = addItemToArray(lineArray, sizeof(lineArray) / sizeof(lineArray[0]), 4)) == nullptr)< cout > I; >

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

  • Вопрос задан более трёх лет назад
  • 8167 просмотров

Комментировать
Решения вопроса 1

Adamos

1. Вы сами себя путаете, используя *(array + i) вместо array[i]
2. Вы создаете новый массив, не удаляя старый. Понятно, что в лабораторной это не критично. Но если вы собрались жить с С++, то либо вам будут резать глаз такие вещи, либо учите другой язык.
3. У вас есть функция, в которую передается массив и элемент. Функция возвращает либо новый массив, либо nullptr. Это противоестественно. Функция должна возвращать ссылку на массив - а новый он или старый, можно решать вне функции. Это кажется неважным, но хороший код базируется именно на таких мелочах, а говнокод растет именно из-за того, что "здесь же и так все понятно".
4. Наконец, в программе трэш. Запрашиваются значения для массива, но они не вводятся в сам массив. В массив добавляется не введенное значение, а 4 (?). lineArray сразу же теряется, поскольку ему присваивается nullptr.

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

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