Разница между передачей указателей на функции по значению и по ссылке - PullRequest
0 голосов
/ 25 января 2012

Я пытаюсь понять разницу между передачей указателей на функции, используя значение и ссылку. В моем случае я удаляю [] переданный указатель. Я предполагаю, что удаление указателя является формой изменения этого указателя. Поэтому, если я передам указатель на массив (скажем, ptr) функции по значению, мне не разрешат «удалить [] ptr» внутри этой функции. Однако, когда я пишу оба способа сделать это (передавая ptr по значению, а также по ссылке), компилятор позволяет мне удалять ptr внутри функции в обоих случаях.

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

// Understanding passing by value and reference for pointers

#include<iostream>

using namespace std;

int* createNew_value(int* _oarr, int &_size);
// createNew_value() appends an integer to the input integer array _oarr. The
// value of _size is incremented by one after the call to createNew_value. The
// pointer to array _oarr is passed by value.

int* createNew_reference(int* &_oarr, int &_size);
// Same functionality as createNew_value(), but here the pointer to array _oarr
// is passed by reference.

void displayIntArray(int* _iarr,int _size);
// Just diplays elements of the passed integer array.

int main()
{
    int *int_array;
    int size;

    cout << "Enter the number of elements:";
    cin >> size;

    int_array = new int [size];

    // Initialize elements of array to consecutive integers. This initialization
    // is only here to ensure that the elements of array are not undefined.
    // Other than that this initialization doesnt serve any purpose

    for (int j = 0; j <= size - 1; j++)
        int_array[j] = j;

    // Display the starting location and elements of the filled array;    
    cout << "[main()]: int_array [before createNew_value()] = " << int_array << endl;
    displayIntArray(int_array,size);

    // Display the starting location and elements of the filled array, after
    // call to createNew_value().

    int_array = createNew_value(int_array, size);

    cout << "[main()]: int_array [after createNew_value()] = " << int_array << endl;
    displayIntArray(int_array,size);

    // Display the starting location and elements of the filled array, after
    // call to createNew_reference().

    int_array = createNew_reference(int_array, size);

    cout << "[main()]: int_array [after createNew_reference()] = " << int_array << endl;
    displayIntArray(int_array,size);

    // Finally delete int_array to prevent memory leak. 
    delete [] int_array;

    return(0);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
int* createNew_value(int* _oarr, int &_size)
// createNew_value() accomplishes the following: It creates a pointer to an
// integer array, called temp, and allocates enough memory for storing (_size +
// 1) elements. It then copies the elements of _oarr into temp, and appends one
// more integer to temp. It then deletes the original array pointer _oarr and
// returns temp. The return value of this function is a pointer to an array with
// one element larger than the input array
{
    int* temp;

    temp = new int [_size + 1];

    //copy elements of old array, _oarr, into temp

    for(int i = 0; i <= _size - 1; i++)
        temp[i] = _oarr[i];

    temp[_size] = temp[_size - 1] + 1;

    _size++;

    cout << "[createNew()]: _oarr = " << _oarr << endl;
    cout << "[createNew()]: temp = " << temp << endl;

    delete [] _oarr;

    // Since _oarr is passed by value, C++ SHOULDNT allow me to delete[] it !!

    // QUESTION: I am passing _oarr by value here. So why does C++ allow me to
    // delete [] it? Isnt deleting equivalent to modification? If yes, how can I
    // modify _oarr if I am passing it my value?

    return(temp);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
int* createNew_reference(int* &_oarr, int &_size)
// createNew_reference() accomplishes the following: It creates a pointer to an
// integer array, called temp, and allocates enough memory for storing (_size +
// 1) elements. It then copies the elements of _oarr into temp, and appends one
// more integer to temp. It then deletes the original array pointer _oarr and
// returns temp. The return value of this function is a pointer to an array with
// one element larger than the input array
{
    int* temp;

    temp = new int [_size + 1];

    //copy elements of old array, _oarr, into temp

    for(int i = 0; i <= _size - 1; i++)
        temp[i] = _oarr[i];

    temp[_size] = temp[_size - 1] + 1;

    _size++;

    cout << "[createNew()]: _oarr = " << _oarr << endl;
    cout << "[createNew()]: temp = " << temp << endl;

    delete [] _oarr;
    return(temp);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void displayIntArray(int* _iarr,int _size)
{
    cout << "{ ";

    for (int n = 0; n <= _size - 2; n++)
        cout << _iarr[n] << ", ";

    cout << _iarr[_size - 1] << " }\n";
}

Ответы [ 2 ]

1 голос
/ 25 января 2012

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

0 голосов
/ 25 января 2012

лучший способ думать об указателях - это как чашка воды. Если вы передадите указатель / ссылку, то будет существовать только 1 стакан воды. Любые изменения в чашке, такие как добавление пищевого цвета, произойдут с чем-либо, использующим эту чашку. Однако проход по значению подобен созданию второй чашки воды, которая идентична, однако, если вы добавите в эту чашку пищевой краситель, оригинальная чашка все еще будет прозрачной.

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

Помогает ли это вам лучше понять?

...