#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
中实现一个复制构造函数(和复制赋值运算符(来复制数组(并且需要一个析构函数来释放数组(。