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


#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;
}

这里,A保持数组的基地址,并且当我调用函数change()时,函数中的指针(p(保持基类中的A的地址的地址。因此,我认为它应该更改数组中对象的数据值,并将该值打印为:

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

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

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

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

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

int A[5] = {1, 2, 3, 4, 5};的情况下,A不包含数组的基地址,A是数组本身。数组的整个内存包含在B对象的内存中。因此,B的每个实例都有自己的数组,当您调用change()并按值向其传递B对象时,会生成该对象的副本,从而生成该数组的

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

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

相关内容

最新更新