C++ [C+;+;]如果通过值传递创建本地副本,为什么原始对象会发生更改?

C++ [C+;+;]如果通过值传递创建本地副本,为什么原始对象会发生更改?,c++,C++,我读过一个类似的问题,关于通过值传递将在函数中创建对象的本地副本。当我尝试这样做时,我的原始对象会被更改,但我不希望它更改 这个测试的目标是尝试传递一个对象,在本地修改它,但保持原始对象不变 在ObjectList头文件中: int **board; 包含构造函数和打印函数的ObjectLise类: ObjectList::ObjectList() { board = new int*[9]; for(int i = 0; i < 9; i++) {

我读过一个类似的问题,关于通过值传递将在函数中创建对象的本地副本。当我尝试这样做时,我的原始对象会被更改,但我不希望它更改

这个测试的目标是尝试传递一个对象,在本地修改它,但保持原始对象不变

在ObjectList头文件中:

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,