C++ [C+;+;]如果通过值传递创建本地副本,为什么原始对象会发生更改?
我读过一个类似的问题,关于通过值传递将在函数中创建对象的本地副本。当我尝试这样做时,我的原始对象会被更改,但我不希望它更改 这个测试的目标是尝试传递一个对象,在本地修改它,但保持原始对象不变 在ObjectList头文件中:C++ [C+;+;]如果通过值传递创建本地副本,为什么原始对象会发生更改?,c++,C++,我读过一个类似的问题,关于通过值传递将在函数中创建对象的本地副本。当我尝试这样做时,我的原始对象会被更改,但我不希望它更改 这个测试的目标是尝试传递一个对象,在本地修改它,但保持原始对象不变 在ObjectList头文件中: int **board; 包含构造函数和打印函数的ObjectLise类: ObjectList::ObjectList() { board = new int*[9]; for(int i = 0; i < 9; i++) {
int **board;
包含构造函数和打印函数的ObjectLise类:
ObjectList::ObjectList()
{
board = new int*[9];
for(int i = 0; i < 9; i++)
{
board[i] = new int[9];
}
for(int i = 0; i < 9; i++)
{
for(int j = 0; j < 9; j++)
{
board[i][j] = 10;
}
}
}
void ObjectList::printB()
{
for(int i = 0; i < 9; i++)
{
for(int j = 0; j < 9; j++)
{
cout << board[i][j] << ",";
}
cout << endl;
}
}
大体上,我创建了这两个对象,并将ObjectList对象传递给LetsChange函数,以尝试并仅在本地修改对象,即仅在函数中:
ObjectList object = ObjectList();
ChangeBoard change = ChangeBoard();
object.printB();
change.LetsChange(object);
cout << endl;
object.printB();
复制对象时,隐式复制构造函数将复制板指针的内容。。。因此,它仍将指向来自原始对象的数据。ex可能需要分配和复制
板
数组以获得您期望的行为。复制对象时,隐式复制构造函数将复制板指针的内容。。。因此,它仍将指向来自原始对象的数据。ex可能需要分配和复制板
数组,以获得您期望的行为。正如其他人所提到的,您的示例并不完整
但是让我试着澄清一下。对象
对象
按值传递,例如LetsChange
函数调用生成对象(例如其成员)的本地副本
在您的情况下,board
将被复制,但不会复制您通过board
指向的已分配内存,我认为它是类ObjectList
的成员
因此,当您修改内存时,从技术上讲,它将“影响”您拥有的对象。正如其他人所提到的,您的示例未满 但是让我试着澄清一下。
对象
对象
按值传递,例如LetsChange
函数调用生成对象(例如其成员)的本地副本
在您的情况下,board
将被复制,但不会复制您通过board
指向的已分配内存,我认为它是类ObjectList
的成员
因此,当您修改内存时,它将在技术上“影响”您拥有的对象。如果没有实际复制内存的复制构造函数(或合适的标准容器),则当您按值传递对象时,将复制指针成员
板
。将复制指针,而不是它指向的数据。这是所谓的浅拷贝,不是深拷贝
这意味着在ChangeBoard::LetsChange
函数中有两个对象,其中board
成员都指向同一位置。一个板
成员的快速打印输出,或者使用调试器,您应该很快就能看到这一点
在函数中,修改此板
指针指向的内存,而不是对象本身的数据。如果您这样做了,例如layout.board=newint*[9]
在函数中,您将修改实际的成员,并且该更改不会反映回调用函数中
如果您有一个析构函数,
delete[]
由board
指向的内存,则复制指针会导致出现错误。因为这样,您将为两个对象释放内存,并且当您以后在原始对象中使用板
成员时,它将不再指向已分配的数据
这是你需要考虑的原因。
我建议您停止使用指针,如果大小是编译时常量,或者大小是在运行时设置的,则使用指针
使用
std::array
或std::vector
您可以使用并且不必担心处理自己的内存、复制和删除。无需实际复制内存的复制构造函数(或合适的标准容器)当您通过值传递对象时,将复制指针成员板
。将复制指针,而不是它指向的数据。这是所谓的浅拷贝,不是深拷贝
这意味着在ChangeBoard::LetsChange
函数中有两个对象,其中board
成员都指向同一位置。一个板
成员的快速打印输出,或者使用调试器,您应该很快就能看到这一点
在函数中,修改此板
指针指向的内存,而不是对象本身的数据。如果您这样做了,例如layout.board=newint*[9]
在函数中,您将修改实际的成员,并且该更改不会反映回调用函数中
如果您有一个析构函数,
delete[]
由board
指向的内存,则复制指针会导致出现错误。因为这样,您将为两个对象释放内存,并且当您以后在原始对象中使用板
成员时,它将不再指向已分配的数据
这是你需要考虑的原因。
我建议您停止使用指针,如果大小是编译时常量,或者大小是在运行时设置的,则使用指针
使用
std::array
或std::vector
您可以使用,而不必担心处理自己的内存、复制和删除。您似乎没有提供复制构造函数。默认的复制构造函数只是复制对象的每个成员(当然,如果为每个成员定义此操作)。将创建板的副本。不过,指针的副本指向与原始指针相同的数据。因此,您正在通过副本更改技术上不属于任何对象的原始数据
您总是可以通过编写复制数据的复制构造函数来解决这个问题
ObjectList object = ObjectList();
ChangeBoard change = ChangeBoard();
object.printB();
change.LetsChange(object);
cout << endl;
object.printB();
10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,
99,10,10,10,10,10,10,10,10,
99,10,10,10,10,10,10,10,10,
99,10,10,10,10,10,10,10,10,
99,10,10,10,10,10,10,10,10,
99,10,10,10,10,10,10,10,10,
99,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,