【问题标题】:Difference between passing pointers to functions by value and by reference按值和按引用传递函数指针之间的区别
【发布时间】:2012-01-24 22:10:30
【问题描述】:

我试图了解使用值和引用将指针传递给函数之间的区别。就我而言,我正在“删除 []”传递的指针。我假设删除指针是修改该指针的一种形式。因此,如果我将指向数组(例如 ptr)的指针按值传递给函数,则不应允许我在该函数内部“删除 [] ptr”。但是,当我编写这两种方法(通过值和引用传递 ptr)时,编译器允许我在这两种情况下删除函数内部的 ptr。

我很困惑,因为我认为我无法删除任何按值传递的指针。我在下面附加了我的简单代码。 Stack Overflow 上有一个related question,但它没有回答我的问题,因为那里的 OP 对修改函数内部的指针不感兴趣。

// 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";
}

【问题讨论】:

    标签: c++ pass-by-reference pass-by-value delete-operator


    【解决方案1】:

    operator delete 不会删除指针本身,它会删除指针指向的对象。因此,您可以根据需要创建任意多个指针值的副本,只要您记得在删除对象时将所有这些值丢弃即可。

    【讨论】:

    • 是的,这很清楚。谢谢。重申一下,如果有一个指针 p1 并且我创建了它的副本 p2 = p1delete p2 那么 p1 和 p2 都是悬空的。我在正确的轨道上吗?
    • 确实如此。另一种方法是使用各种智能指针中的一种来为您处理无聊的事情。
    【解决方案2】:

    思考指针的最佳方式就像一杯水。如果您传递一个指针/引用,则只有 1 杯水存在,任何对杯子的更改,例如添加食物颜色,都会发生在使用该杯子的任何东西上。然而,通过价值传递就像创造第二杯相同的水,但是如果你在那个杯子中添加食用色素,原来的杯子仍然是透明的。

    当您通过引用传递时,您通常希望影响内存中的对象,而无需将其返回给调用函数。如果作为值传递,您必须将其返回到前一个函数并覆盖前一个对象。

    这是否有助于您更好地理解它?

    【讨论】:

    • 那种。我认为即使在这种情况下也有两个杯子,因为通过“值”传递指针会创建另一个指向原始指针位置的指针。然而,事实并非如此。按值传递指针似乎不会创建它的副本。
    猜你喜欢
    • 2020-04-10
    • 1970-01-01
    • 2011-01-30
    • 2011-08-19
    • 2013-06-29
    • 1970-01-01
    • 2018-04-05
    • 2012-01-24
    相关资源
    最近更新 更多