2013-06-26 3 views
1

Если у меня есть указатель на C++, скажем int* array;, я выделить память для массива сДинамическое распределение в Java или C++

array=new int[10]; 

Затем я инициализировать все 10 элементов массива, с 0,1 , 2,3 ... После этого я сделаю array=new int[15]; будут ли первые первые 10 значений? Я предполагаю, что нет, исправьте меня, если я ошибаюсь.

В C есть функция realloc, которая имеет эффект, описанный выше. Есть ли эквивалент в C++ или java? Как я могу динамически расширять массив (без использования класса Vector и без копирования массива каждый раз в другом массиве с двойной емкостью) на C++ или Java?

+0

Вы правы. Он будет заменен массивом нулей в Java. – asteri

+0

Нет, он заменит массив случайных значений (на самом деле то, что было в памяти раньше). C++ не инициализирует содержимое массива! – Marius

+3

Я думаю, что это слишком неопределенный вопрос - несколько вопросов на разных языках ... –

ответ

3

Всякий раз, когда вы делаете new int[X] где X целое, как в C++ и Java, вы получите ссылку на вновь выделенный массив.

В Java массивы автоматически инициализируются так, что каждая запись имеет значение по умолчанию (0 для примитивных типов данных, null для ссылочных типов данных). В C++ массив не инициализирован, вы получаете мусор на нем.

Если вы:

array = new int[10]; 
array[0] = 0; 
array[1] = 1; 
// etc 
array = new int[15]; 

второй раз, когда вы создаете массив и поместить ссылку на него в переменной array, вы просто потеряете ссылку на ваш первый массив. Поскольку это массив , он будет подчиняться правилам языка для новых распределенных массивов: в Java массив теперь укажет на массив размером 15, заполненный нулями; в C++ массив укажет на массив размером 15, заполненный мусором.

В Java потерянный массив будет в конечном итоге собранным для вас мусором. В C++ вы только что создали утечку памяти.

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

В Java нет перераспределить (но это имеет Arrays.copyOf, который работает аналогично), и в C++ (и C, а), realloc не очень продлить массива; он будет выделять больше памяти в другом месте, освободить ранее выделенную память и вернуть новый указатель: вам придется заменить любые существующие указатели на новый адрес!

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

+0

Лучший ответ до сих пор :) Не могли бы вы подробнее остановиться на последней части , с realloc? почему он работает в C, а не в C++ (для примитивных типов, я имею в виду) – Radu

+0

Как это так, «это не работает на C++»? –

+0

@Radu 'realloc' работает одинаково на C и C++. – juanchopanza

0

В Java вы не можете динамически расширять массив. Существуют разные структуры данных для таких, как ArrayList.

В Java, в вашем примере, если в первый массив размером 10 не указывается ссылка, он будет собран GarbageCollector.

+0

Вот что я хотел знать, если вы можете или нет динамически расширять массив. Как вектор внутренне работает? – Radu

+0

Используйте ArrayList вместо Vector, если вам не нужна его потоковая безопасность. У него есть массив внутри него. Когда вы заполняете все пространство и вам нужно добавить одну mroe, он копирует все в более крупный массив и выпускает ссылки на предыдущий массив (так что это сбор мусора) – Tala

1

будут ли первые первые 10 значений еще там?

В C++, будет где-то , но вы потеряли ручку к ним. Они будут недоступны. Это приводит к утечке памяти.

int* array=new int[10]; // array points to dynamically allocated array 
array=new int[15]; // array points to a completely different place now 

В приведенном выше примере, array указатель является единственной ручкой у вас есть на первом динамически распределяемой массива. Сделав это в другом месте, вы пропустите массив.

Обратите также внимание, что в C++ элементы массива не инициализируются нолем. Для того, чтобы сделать это, вам нужно дорожить инициализировать массив:

int* array=new int[10](); 
//     ^^ 
1

В управлении памятью Java управляет JVM. Это красота java. Вы можете использовать функцию System.arraycopy(), чтобы сделать копию массива. Если ваша цель состоит в расширении массива, просто укажите массив большего размера в качестве целевого массива.

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

0

В C++ new всегда возвращает указатель. Имя массива - это указатель на первый элемент массива, поэтому вот что произойдет.

int *array;   //get a point of type int 
array=new int[10]; //allocate 10 ints, and set the array ponter to the first one 

array = new int[15] //allocate 15 ints, and set the array pointer to the first one 

проблема в том, что у нас нет способа узнать, где в памяти первые 10 целых чисел. Операционные системы «думают», что мы используем его b/c, мы его просили. но мы не можем использовать его b/c, мы не знаем, где он находится.


сейчас для чего-то полезного. Используйте векторы, векторы - это объекты в C++, в которые встроено динамическое распределение памяти, поэтому вам не нужно вручную делать это самостоятельно.

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

0

Как можно динамически развернуть массив (без использования класса Vector и без копирования массива каждый раз в другом массиве с двойной емкостью) в Java?

java.util.Arrays, есть много методов использования. В вашей ситуации вам нужно copyOf

Api Docs

array = Arrays.copyOf(array, 15); 
+0

_without копирование массива каждый раз_ ... – jlordo

+0

@jlordo Я думаю, что OP означает без * вручную * копирование массива каждый раз ... – johnchen902

+0

Это неправильно. Массив не будет расширяться, вы просто получите новый выделенный массив. Любые ссылки на старый массив все равно указывают на старый массив со старым размером. –

0

Да, есть эквивалент в C++, который является стандарт C++.

std::vector<int> array(10); 

А потом

array.resize(15); 

vector управляет памятью для хранения именно так, как вы ожидаете. vector был разработан для замены перераспределенных указателей массива C. Чтобы заменить массивы на стеке, у вас есть std::array с C++ 11. Чтобы заменить VLA на стеке, у вас будет std::dynarray в C++ 14 или C++ 17.

И не заманивать, realloc иногда копирует свои данные. (Когда он не находит достаточно мест на месте, чтобы получить ваш перераспределен буфер)

О эквиваленте realloc для C++, нет, нет renew, соответствующего new пути есть realloc, соответствующий malloc. И это не что-то не хватает на языке. Он был рассмотрен с классом std::vector. Он управляет своей памятью, она эффективна, и нет, это не непристойный стиль для ее использования. Это стандартный способ в C++ иметь массив, который может изменять размер.

0

Лучший вариант в C++ - stl и std::vector<int> Я понятия не имею, почему вы не можете его использовать, но не говорите, что вы не можете. Вероятно, наилучшим образом:

const int c_startSize = 10; 
const int c_increasing = 13; //1.3 

int * array; 
int arraySize = c_startSize; 
array = new int[arraySize]; 
//some code 
//now we need to increase size of array. 
int * tmp; 
tmp = new int[arraySize * c_increasing/10]; 
for (int i = 0; i < arraySize; i++) 
    tmp[i] = array[i]; 
arraySize = arraySize * c_increasing/10; 
delete [] array; 
array = tmp; 
//some code 

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

EDIT: Забытый, мой ответ включает только C++, без JAVA.

+0

В основном вне темы. Во-первых, это не стандартная библиотека STL, несмотря на то, что большинство людей путают между собой, они разные. Во-вторых, я попросил что-то совершенно другое. Знаете ли вы, что означает «без использования вектора и без копирования массива»? В-третьих, откуда у вас появилась идея, что я новичок? В-четвертых, это не помогло. Меня это очень раздражает, когда люди отвечают на вопросы, которые не задавались. – Radu

+1

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

2

Основой концепции массива, как на C++, так и Java, является исправлено размер коллекции. realloc может выглядеть как бэкдор в этой концепции, но он по-прежнему не обещает расширить данный массив - он может создавать массив в другом месте, копировать исходный контент и выпускать исходную память. И, скорее всего, это произойдет.
Итак, если вы хотите коллекцию переменных размеров, используйте std::vector в C++ и ArrayList в Java. Или вы можете закодировать эту функцию самостоятельно. Но я боюсь, вам придется начинать с собственного распределителя памяти, так как вы не можете сделать стандартным один раз распределенный блок памяти.

Смежные вопросы