提问人:Harsh Kumar 提问时间:10/9/2022 最后编辑:Remy LebeauHarsh Kumar 更新时间:10/9/2022 访问量:40
我将一个函数称为按值传递,而不是按引用传递,但有一次它正在更改值,但在第二种情况下没有,为什么?
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?
问:
#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 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
答:
如果 ,则不包含数组的基址,而是数组本身。数组的整个内存包含在对象的内存中。因此,每个实例都有自己的数组,当您调用按值传递对象时,会创建对象的副本,从而创建数组的副本。然后,该函数将修改复制的数组,而不是原始数组。这就是为什么您看不到正在更改的数据。int A[5] = {1, 2, 3, 4, 5};
A
A
B
B
change()
B
main()
在 的情况下,DOES 包含数组的基址,而不是数组本身。数组存储在内存中的其他位置,并且仅指向它。因此,最初的每个实例都有自己的数组,但是当您调用按值传递对象时,会创建对象的副本,从而复制指向数组的指针(违反 3/5/0 规则),实际数组本身不会被复制。然后,该函数使用复制的指针来修改原始数组,而不是数组的副本。这就是为什么您确实会看到数据正在更改的原因。int *A = new int[5]{1, 2, 3, 4, 5};
A
A
A
B
change()
B
main()
要解决第二种情况,您需要实现一个复制构造函数(和复制赋值运算符)来复制数组(并且您需要一个析构函数来释放数组)。B
评论
A
A
new
评论
class B
new
first
change()