我将一个函数称为按值传递,而不是按引用传递,但有一次它正在更改值,但在第二种情况下没有,为什么?

I am calling a function as pass by value, not pass by reference, but one time it is changing the value but not in the 2nd case, why?

提问人:Harsh Kumar 提问时间:10/9/2022 最后编辑:Remy LebeauHarsh Kumar 更新时间:10/9/2022 访问量:40

问:

#include <iostream>
using namespace std;

class B
{
    int a = 10;
    int b = 20;
    int A[5] = {1, 2, 3, 4, 5};// int *A = new int[5]{1, 2, 3, 4, 5};

public:
    friend void change(B);

    void print()
    {
        for (int i = 0; i < 5; i++)
        {
            cout << " " << A[i];
        }

        cout << endl;
    }
};

void change(B obj)
{
    int *p = obj.A;
    for(int i = 0; i < 5; i++)
    {
        *p += 10;
        p++;
    }
}

int main()
{
    B first;
    first.print();
    change(first);
    first.print();
    change(first);
    first.print();
    return 0;
}

这里,保存数组的基址,当我调用函数时,函数中的指针 () 保存基类中该地址的地址。所以,我认为它应该改变数组中对象的数据值,它应该将值打印为:Achange()pA

1 2 3 4 5
11 12 13 14 15 21 22 23 24 25

但它不是那样的,它正在打印这个:

1 2 3 4 5 1 2 3 4 5
1 2 3 4 5

但是,当我使用堆上的数组时,它会按我的预期工作。int *A=new int[5]{1, 2, 3, 4, 5};

那么,我如何知道数据的值何时会改变,什么时候数据不会改变呢?在这两种情况下,都有指向原始数组地址的指针,但在一种情况下它正在更改值,而在另一种情况下它没有更改,为什么?请详细解释一下。A

C++ 指针 按引用传递

评论

0赞 UnholySheep 10/9/2022
它“按预期工作”的原因是,您没有实现复制构造函数,因此在其中使用 违反了 3 规则,如果您没有泄漏内存,这将破坏您的整个代码class Bnew
0赞 JaMiT 10/10/2022
“in the base class” -- 代码中没有继承,因此没有基类。我不知道你在这里的目的是什么。我最好的猜测是你指的是 main 函数中的变量,但这是一个对象,而不是一个类,它超出了 .firstchange()

答:

1赞 Remy Lebeau 10/9/2022 #1

如果 ,则不包含数组的基址,而是数组本身。数组的整个内存包含在对象的内存中。因此,每个实例都有自己的数组,当您调用按值传递对象时,会创建对象的副本,从而创建数组的副本。然后,该函数将修改复制的数组,而不是原始数组。这就是为什么您看不到正在更改的数据。int A[5] = {1, 2, 3, 4, 5};AABBchange()Bmain()

在 的情况下,DOES 包含数组的基址,而不是数组本身。数组存储在内存中的其他位置,并且仅指向它。因此,最初的每个实例都有自己的数组,但是当您调用按值传递对象时,会创建对象的副本,从而复制指向数组的指针(违反 3/5/0 规则),实际数组本身不会被复制。然后,该函数使用复制的指针来修改原始数组,而不是数组的副本。这就是为什么您确实会看到数据正在更改的原因。int *A = new int[5]{1, 2, 3, 4, 5};AAABchange()Bmain()

要解决第二种情况,您需要实现一个复制构造函数(和复制赋值运算符)来复制数组(并且您需要一个析构函数来释放数组)。B

评论

0赞 Harsh Kumar 10/9/2022
在这里,我将如何知道何时存储原始地址和何时存储复制数据的地址
0赞 Remy Lebeau 10/10/2022
当对象按值复制,并且类未显式实现复制构造函数时,默认生成的复制构造函数仅按值复制类字段。在第一种情况下,是实际的数组,因此数组被复制。在第二种情况下,只是一个指向数组的指针,复制指针,而不是数组。它真的知道如何让你更清楚。AA
0赞 Harsh Kumar 10/10/2022
这是我 stackoverflow.com/questions/74005913/ 提出的问题链接......。您已经让我理解的第一个代码,但是在第 2 个代码中,当我首先在函数中传递对象时,应该为 obj 创建一个数组,指针 p 应该指向 obj 的数组,并且不应该对第一个数组的数组进行更改然后为什么会发生更改。请向我解释与此相关的所有概念.
0赞 Remy Lebeau 10/11/2022
@HarshKumar 在您的另一个问题(已删除)中,您正在制作数组本身的副本,但您也在制作指向原始数组的指针的副本,而不是复制的数组。Hense 为什么要修改原件。与此问题中的代码类似,当使用并复制该指针时。我有一种感觉,你并不真正理解指针到底是什么,以及记忆是如何工作的。我强烈建议你给自己买一些好的C++书籍来学习。new