【问题标题】:Pointer error - "using uninitialized value" even though I think it is initialized?指针错误 - “使用未初始化的值”,即使我认为它已初始化?
【发布时间】:2021-02-21 06:08:24
【问题描述】:

我说的是这段代码:

#include <iostream>

using namespace std;

void citire(int& n, int* a)
{
    cin >> n;
    a = new int[100];
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
}

int main()
{
    int n, *a;
    citire(n, a);
    for (int i = 0; i < n; i++)
    {
        cout << *a << " ";
    }
    return 0;
}

我收到一条错误消息,提示 a 未初始化,我似乎无法理解原因。我在该函数中使用了a = new int[100],而a 是一个指针,所以我在哪里初始化它并不重要(只要我在使用它的值之前做)。

如果我在 int main() 中的函数调用 citire(n, a) 之前添加该行,则代码将起作用。

我可能认为产生错误的唯一原因是初始化发生在函数中。所以,如果我不打电话给citire(n, a),那么a 将是未初始化的。这是错误的原因吗?

或者为什么我会得到它?

编辑:

出现混淆是因为我知道数组基本上是指针,并且在将数组作为参数传递时,如下所示:

#include <iostream>

using namespace std;

void citire(int& n, int a[])
{
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
}

int main()
{
    int n;
    int a[100];
    citire(n, a);
    for (int i = 0; i < n; i++)
    {
        cout << *a << " ";
    }
    return 0;
}

我不需要通过引用传递它——创建了一个浅拷贝。

为什么默认情况下使用数组会发生这种情况,但不会使用指针? (虽然现在我的程序崩溃的原因很清楚了。)

【问题讨论】:

  • citire::amain::a 的副本,因为它是按值传递的。您希望通过引用传递它(就像您所做的 n 一样)。旁注:您正在泄漏内存 - 使用 std::vector&lt;int&gt; 而不是赤裸裸的 new
  • 你将a 按值传递给函数,所以函数中的赋值只会赋值给局部变量。 main 函数中的a 变量不会被修改。
  • void citire(int&amp; n, int* a) -> void citire(int&amp; n, int*&amp; a)。它变得难以阅读,不是吗?请改用std::vector
  • Close voter:问题不是由拼写错误引起的,而是对传递指针的工作原理的误解。没有理由结束这个问题。而且我也不明白为什么它应该被否决;有一个minimal reproducible example,很清楚。
  • 请提出一个新问题,而不是编辑来提出一个新问题。这对回答者不公平。

标签: c++ pointers


【解决方案1】:

我认为您应该进一步了解如何在 C 函数中传递参数。

首先,虽然a是一个指针,但它的内存分配发生在citire()中,其中a被分配了它的新内存地址。 但是 a 在citire() 中作为值传递。 当程序返回main() 时,您仍然拥有之前的a 值。

其次,如果您将未初始化的指针传递给函数,编译器会警告您,因为它假定您将使用指针 (e.g. *a = 8),并且由于未初始化,它可能会导致崩溃。

你最好改变你的函数原型:

int * cintire(int& n);
void cintire(int& n, int *& a);

Z.

【讨论】:

    【解决方案2】:

    我修复了你的代码,还打印了一些地址供你理解。

    旧代码:

    #include <iostream>
    
    using namespace std;
    
    void citire(int& n, int* a)
    {
        cin >> n;
        a = new int[100];
        for (int i = 0; i < n; i++)
        {
            cin >> a[i];
        }
        cout << "In citire Address of a = " << &a <<endl;
        cout << "In citire Address of n = " << &n <<endl;
    }
    
    int main()
    {
        int n, *a;
        cout << "Address of a = " << &a <<endl;
        cout << "Address of n = " << &n <<endl;
        citire(n, a);
        for (int i = 0; i < n; i++)
        {
            cout << *a << " ";
        }
        return 0;
    }
    

    输出:

    Address of a = 0x7ffee5ab6b90
    Address of n = 0x7ffee5ab6b98
    5
    1 2 3 4 5
    In citire Address of a = 0x7ffee5ab6b50
    In citire Address of n = 0x7ffee5ab6b98
    0 0 0 0 0
    

    注意main()citire()函数内部变量an的地址。

    修改代码:

    #include <iostream>
    
    using namespace std;
    
    void citire(int &n, int* &a)
    {
        cin >> n;
        a = new int[n];
        for (int i = 0; i < n; i++)
        {
            cin >> a[i];
        }
        cout << "In citire Address of a = " << &a <<endl;
        cout << "In citire Address of n = " << &n <<endl;
    }
    
    int main()
    {
        int n, *a;
    
        cout << "Address of a = " << &a <<endl;
        cout << "Address of n = " << &n <<endl;
    
        citire(n, a);
    
        for (int i = 0; i < n; i++)
        {
            cout << a[i] << " ";
        }
    
        delete [] a;
        return 0;
    }
    

    输出:

    Address of a = 0x7ffee0eb1b90
    Address of n = 0x7ffee0eb1b98
    5
    1 2 3 4 5
    In citire Address of a = 0x7ffee0eb1b90
    In citire Address of n = 0x7ffee0eb1b98
    1 2 3 4 5
    

    注意在这种情况下,na 的地址在函数内部和main 中都是相同的。由于它们是passed by reference,因此实际变量(只是别名)在其内存位置完好无损的情况下传递,对它们所做的任何更改也会反映在main 中。

    要点:即使pointers 也会被value 传递给函数,除非你强制它通过reference

    编辑(数组代码):

    #include <iostream>
    
    using namespace std;
    
    void citire(int& n, int a[])
    {
        cin >> n;
        for (int i = 0; i < n; i++)
        {
            cin >> a[i];
        }
        cout << "In citire Address of a = " << &a <<endl;
        cout << "In citire Address of n = " << &n <<endl;
        cout << "In citire Address of first element of a = " << &a[0] <<endl;
    }
    
    int main()
    {
        int n;
        int a[100];
        cout << "Address of a = " << &a <<endl;
        cout << "Address of n = " << &n <<endl;
        cout << "Address of first element of a = " << &a[0] <<endl;
        citire(n, a);
        for (int i = 0; i < n; i++)
        {
            cout << a[i] << " ";
        }
        return 0;
    }
    

    输出:

    Address of a = 0x7ffeef1cda00
    Address of n = 0x7ffeef1cd9f8
    Address of first element of a = 0x7ffeef1cda00
    5
    1 2 3 4 5
    In citire Address of a = 0x7ffeef1cd9b0
    In citire Address of n = 0x7ffeef1cd9f8
    In citire Address of first element of a = 0x7ffeef1cda00
    1 2 3 4 5
    

    请注意,在arrays 的情况下,即使它们是按值传递的,从某种意义上说,a 的地址在函数调用中发生了变化,区域的地址(即,您拥有的 100 个整数)静态声明),基本上是数组第一个元素的地址(&amp;a[0]不要改变。可以这样想:

    • 你有一个黑盒子,里面存储了一个数字,它是a[0]的地址,这是a指向的实际区域。
    • 现在假设黑匣子本身有一个标识号XXX
    • 在函数调用期间,您将黑匣子XXX内容 放入另一个黑匣子,例如标识号YYY
    • 不明白YYY 具有相同的指向区域,即&amp;a[0]
    • 您将新的YYY 黑盒发送到使用和操作从&amp;a[0] 开始的区域中的数据的功能。

    所以你得到的结果反映在main() 中。另请注意,arraypointer 类型相同。

    【讨论】:

    • 知道了。我希望它无论如何都能工作,因为如果不使用指针,我会使用简单数组而不是指针,我不需要通过引用传递它。
    • 首先要明白数组不是指针,指针也不是数组。检查这个答案:stackoverflow.com/questions/1461432/….
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多