Копирование из одного динамически размещенного массива в другой C++

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

void ResizeArray(int *orig, int size) {
    int *resized = new int[size * 2]; 
    for (int i = 0; i < size; i ++)
        resized[i] = orig[i];
    delete [] orig;
    orig = resized;
}

Кажется, что здесь происходит то, что resized[i] = orig[i] копирует значения по ссылке, а не по значению, поскольку печать orig после изменения размера возвращает кучу ненужных значений, если я не закомментирую delete [] orig. Как я могу сделать глубокую копию из оригинала в измененный размер, или есть какая-то другая проблема, с которой я сталкиваюсь? Я не хочу использовать std::vector.


person Rahul Gupta-Iwasaki    schedule 08.11.2011    source источник
comment
Обратите внимание, что нет такой вещи, как копирование значений по ссылке. Либо вы создаете новую ссылку на те же данные, либо копируете.   -  person André Caron    schedule 09.11.2011
comment
Даже если вы не хотите использовать std::vector, вы многое выиграете, заключив это в класс, чтобы клиенты могли передавать инвариантный объект и не должны были управлять тем фактом, что указатель реализации меняется при каждом изменении размера. :-/   -  person HostileFork says dont trust SE    schedule 09.11.2011


Ответы (3)


Помните, что параметры в C++ передаются по значению. Вы присваиваете resized копии переданного вам указателя, указатель вне функции остается прежним.

Вы должны либо использовать двойную косвенность (или "двойной указатель", т.е. указатель на указатель на int):

void ResizeArray(int **orig, int size) {
    int *resized = new int[size * 2]; 
    for (int i = 0; i < size; i ++)
        resized[i] = (*orig)[i];
    delete [] *orig;
    *orig = resized;
}

или ссылка на указатель:

void ResizeArray(int *&orig, int size) {
    int *resized = new int[size * 2]; 
    for (int i = 0; i < size; i ++)
        resized[i] = orig[i];
    delete [] orig;
    orig = resized;
}

Кстати, для размеров массива следует использовать тип std::size_t из <cstddef> — он гарантированно содержит размер для любого объекта и дает понять, что мы имеем дело с размером объекта.

person Matteo Italia    schedule 08.11.2011
comment
+1 Другой вариант - вернуть новый массив, используя... возвращаемое значение. - person André Caron; 09.11.2011
comment
@AndréCaron: это тоже вариант, но я думаю, что эти формы лучше подходят для использования с отступом. - person Matteo Italia; 09.11.2011
comment
В качестве пояснения, под двойным указателем респондент подразумевает двойную косвенность. Когда я впервые прочитал это, я был озадачен, почему он хотел заменить double * на int *. - person Michael Price; 09.11.2011

Я настоятельно рекомендую заменить массивы на std::vector<int>. Размер этой структуры данных будет изменяться по мере необходимости, и изменение размера уже было проверено.

person Thomas Matthews    schedule 08.11.2011

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

int **orig;
*orig = resized;
person Drew    schedule 08.11.2011