【问题标题】:Modifiying array pointers inside a function修改函数内部的数组指针
【发布时间】:2013-11-13 03:32:05
【问题描述】:
    void nothing(int* buffer)
    {
        int* temp = new int[5];
        for (int i = 0; i < 5; i++)
        {
            temp[i] = i;
        }
        buffer = temp;
    }

    void main(int argc, char* argv[])
    {
        int* a = new int;
        nothing(a);
        for (int i = 0; i < 5; i++)
        {
            cout << a[i] << endl;
        }
        system("pause");
    }

为什么我不能从缓冲区获取新地址?我正在尝试将一个数组(指针)传递给函数并在里面修改它。

输出:

 -842150451
-33686019
-1414812757
-1414812757
0

预期:

0
1
2
3
4

【问题讨论】:

  • this问题及相应答案。

标签: c++ arrays pointers


【解决方案1】:

重要的前奏:如果可以的话,使用vector 代替数组/指针。我们都会尽可能地鼓励这一点!很可能连续数月编程,编写一些相当复杂的软件,而不必打电话给newdelete,也不必担心所有那些讨厌的 C 问题。


停止使用temp

void nothing(int* buffer)
{
    for (int i = 0; i < 5; i++)
    {
        buffer[i] = i;
    }
}

这将把一个指向你的数组的指针作为输入。然后它将直接写入该数组。

您之前的代码创建了第二个数组。每次调用 new 时,都会得到一个新数组。 int* temp = new int[5];。要使这种方法起作用,您需要将临时数组中的数据复制到缓冲区数组。但是,您不能(轻松地)在 C 中复制数组。

buffer = temp;  // This *doesn't* copy any array

这条线什么也没做。这两个数组仍然存在,因此没有数据被复制。这里修改了名为buffer 的局部变量;但是变化很小——缓冲区曾经指向旧数组,现在它指向新数组。而且由于 buffer 是一个局部变量,一旦函数返回它就失去了所有意义(它指向非本地数据,但 buffer 指针本身仍然是本地的。

简而言之,您原来的 nothing 函数没有任何用处。它创建了一个新数组,将一些值放入其中,然后忽略它。 main 中的缓冲区变量不受您的函数影响。

【讨论】:

    【解决方案2】:

    您需要通过指针传递指针(或其他人指出对指针的引用),即int **,然后使用*buffer = temp 分配并使用nothing(&amp;a) 调用函数。

    如果您不这样做,您对缓冲区变量所做的更改会在您离开函数时丢失。将指针变量本身想象成任何数字,因为它指向的东西在函数结束后仍然存在。

    但是,我建议您改用 std::vector:

    void nothing(std::vector<int> &buffer) {
        ...
    }
    
    int main(int argc, char* argv[])
    {
        std::vector<int> a;
        nothing(a);
        for (int i = 0; i < 5; i++)
        {
            cout << a[i] << endl;
        }
        system("pause");
        return 0;
    }
    

    根据您的场景,您甚至可能希望将 nothing 函数更改为初始化样式函数,即直接返回一个对象:

    std::vector<int> nothing() {
        std::vector<int> temp;
        // fill vector here
        return temp;
    }
    
    int main(int argc, char* argv[])
    {
        auto a = nothing();
        for (int i = 0; i < 5; i++)
        {
            cout << a[i] << endl;
        }
        system("pause");
        return 0;
    }
    

    这更像是 C++ 风格,让您不必手动删除数组。

    要实际将数据生成到向量中,请查看Initialization of std::vector<unsigned int> with a list of consecutive unsigned integers .

    【讨论】:

      【解决方案3】:

      指针buffer 是按值传递的(这是c++ 中的默认值),这意味着创建了一个副本。然后,您修改此副本。这是 c++,你可以传递一个引用:

      void nothing(int*& buffer)
      

      这样传递的是原始对象,而不是副本。

      【讨论】:

        【解决方案4】:

        temp 是一个局部变量,在 nothing() 中声明。这意味着 temp 的内存在 nothing() 返回时丢失。您无法从局部变量中取回数据 - 因此是垃圾。

        【讨论】:

        • 问题不在于 temp 是一个局部变量,因为 temp 中的值被复制到缓冲区中。问题是缓冲区也是一个局部变量。
        【解决方案5】:

        “我正在尝试将一个数组(指针)传递给函数并在里面修改它”

        但是您的代码所做的是它为 1 int 分配内存,将指向该内存的指针传递给您的函数,您的函数分配一个数组并尝试将地址或这个新分配的数组分配给传递的指针,即它试图修改指针本身

        尝试传递 int** 而不是 int* 并让调用者这样做:

        int* a;
        nothing(&a);
        

        还请注意,在 C++ 中,函数动态分配一些资源并以释放这些资源的责任形式引发负担(即使使用特定方法,在这种情况下调用 delete[] ) 给来电者。考虑使用诸如std::vector 之类的 STL 容器,或者如果您必须坚持使用 C 样式的数组,那么至少更喜欢那些具有自动存储持续时间的容器。

        【讨论】:

          【解决方案6】:

          a 是按值传递的,因此将它的副本更改为 nothing 对 a 没有影响。如果通过引用,您必须通过,或者正如@villintehaspam 所说,将指针传递给指针。

          【讨论】:

            猜你喜欢
            • 2020-08-21
            • 2016-11-07
            • 2015-06-21
            • 2022-01-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-07-16
            相关资源
            最近更新 更多