Расширение емкости массива - PullRequest
2 голосов
/ 30 марта 2011

Я думал о способах быстрого увеличения массива в C ++ и придумал следующее:

// set up arr1
int *arr1 = new int[5];

// add data to arr1
arr1[0] = 1;
arr1[1] = 2;
arr1[2] = 3;
arr1[3] = 4;
arr1[4] = 5;

// set up arr2
int *arr2 = new int[10];
arr2 = arr1; // assign arr1 to arr2

// add more values
arr2[5] = 6;
arr2[6] = 7;
arr2[7] = 8;
arr2[8] = 9;
arr2[9] = 10;

Это даже безопасно?Я беспокоюсь о том, что это вызовет какое-то странное поведение, и что arr2 - это просто массив int [5], и теперь вы перезаписываете данные, которые ему не принадлежат.

Ответы [ 7 ]

8 голосов
/ 30 марта 2011

NO.

arr2 = arr1;

Не делает то, что, как вы думаете, делает!

В STL уже есть что-то для этого, оно называется vector.


Ради полноты ..:)

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

  1. У вас больше нет адреса блока из 10 выделенных вами элементов, поэтому у вас нет возможности освободить этот блок - следовательно, у вас утечка памяти (если ваша программа продолжит работать)
  2. Хотя изначально вы выделили 10 элементов для arr2, в соответствии с заданием вы теперь обращаетесь к блоку, который имеет только 5 элементов, и доступ к чему-либо за пределами этого блока из 5 (т. Е. Индексов 5 и более), вероятно, закончится в носовых демонах, посещающих с очень большой крикетной битой - или вам повезет ...

Итак, что вы можете сделать:

  1. Используйте std::vector<int>, один из его конструктивных особенностей - избавиться от этого вида бремени. от вас (если вы не заинтересованы в реализации другого контейнера), если это так
  2. Используйте операцию копирования для правильного копирования содержимого, а не присваивайте адреса, как предложено, используйте std::copy - или другие, например memcpy (предпочитайте memmove - это немного медленнее, но хорошо определено для перекрытия блоки и т. д.)
6 голосов
/ 30 марта 2011

Строка arr2 = arr1; приводит к утечке памяти, и все последующие arr2[...]= строки вызывают неопределенное поведение, когда они обращаются к массиву из 5 дюймов вне его границ.

Чтобы сделать то, что вы хотели сделать, заменитеarr2 = arr1; с std::copy(arr1, arr1+5, arr2); (пример программы: https://ideone.com/3Rohu)

Чтобы сделать это правильно, используйте std::vector<int>

5 голосов
/ 30 марта 2011

Это приводит к утечке памяти, потому что вы назначаете указатели.

int *arr2 = new int[10];
arr2 = arr1; // this does not assign the values

Второе назначение arr2 указывает на массив arr1. Вы теряете ранее выделенный массив и не можете его удалить.

Чтобы избежать этого, используйте std::vector.

3 голосов
/ 30 марта 2011

Нет, это совсем не безопасно.Когда вы сказали arr2=arr1;, что не скопировали данные, вы просто переназначили указатель.Теперь память, выделенная вами с помощью int *arr2 = new int[10];, утечка, и arr2 указывает на исходный массив из 5 элементов, и когда вы начинаете говорить что-то вроде arr2[5] = 6;, вы пишете за пределами этого массива, и весь ад может сломатьсясвободный.

2 голосов
/ 30 марта 2011

Просто чтобы добавить к другим комментариям, которые являются правильными.Причина утечки памяти в том, что вы заменили указатель arr2, который указывал на выделенную память для arr2, указателем arr1.Теперь arr1, arr2 указывают на то же самое, массив из 5 элементов.Когда вы пытаетесь очистить с помощью оператора delete, вы можете очистить только массив из 5 элементов, так как указатель на массив из 10 элементов был переопределен.

2 голосов
/ 30 марта 2011

Это даже безопасно?

Нет

arr2 = arr1;// присваиваем arr1 arr2

arr2 также указывает на первый элемент индекса arr1.И, делая это, arr2 теряет место, на которое оно ранее указывало, возвращаемое new.Итак, утечка памяти .

Используйте вместо этого std :: vector для расширения массива.

2 голосов
/ 30 марта 2011

Это не безопасно, это на самом деле утечка памяти.Вы ничего не делаете с arr2, вы просто настроили arr2 на адрес r1, помните, что в c и c ++ нет проверки границ, поэтому вы перезаписываете другой стек, делая это

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...