C++ 修改通过引用传递的 class 不会更改原始对象

C++ modifying a class passed by reference does not change the original object

我有一个包含几个实例变量的 class A 和一个引用 class 并更改实例变量的 class B。在 class B 更改这些变量后,您会认为这些变量会在 class 的原始实例中发生更改,但在这种情况下它们不会。为什么会发生这种情况,我该如何解决?

class Foo {
public:
    int x;
    int y;
    Foo() {

    }
    Foo(int x, int y) {
        this->x = x;
        this->y = y;
    }
};

class Bar {
public:
    Foo foo;
    Bar() {

    }
    Bar(Foo& foo) {
        this->foo = foo;   
    }
    void Swap() {
        int tmp = foo.x;
        foo.x = foo.y;
        foo.y = tmp;
    }
};
int main()
{
  Foo foo(4, 8);
  Bar bar(foo);

  std::cout << "this is x: " << foo.x << std::endl; //prints 4
  std::cout << "this is y: " << foo.y << std::endl; //prints 8

  bar.Swap();
  std::cout << "this is x: " << foo.x << std::endl; //prints 4, but should print 8
  std::cout << "this is y: " << foo.y << std::endl; //prints 8, but should print 4
}

您将对 foo 的引用传递给 bar 的构造函数,然后将您通过引用传递给 bar.foo.

的 foo 赋值(复制)

您想将其声明为对 Foo 对象的引用(或指针),而不是单独的 Foo 对象。

Class B 的构造函数确实通过引用获取 foo(参数),但立即将其复制到 A 的单独实例中(特别是,进入 foo 成员); Swap 然后在 foo 成员上工作,如上所述,它只是原始对象的副本。

为了使您的代码按照您的预期运行,您甚至必须使成员 foo 成为引用(或指针):

class Bar {
public:
    Foo &foo;
    Bar() {

    }
    Bar(Foo& foo) : foo(foo) {
    }

(注意我必须使用 the member initialization list syntax because references cannot be default-initialized and then reseated

问题就在这里

    Foo foo;
    Bar(Foo& foo) {
        this->foo = foo;   
    }

即使您通过引用获取 foo 参数,您也将其分配给了一个非引用值,这会产生一个副本并说明您提出的问题。解决方案的第一步也是通过引用声明您的实例字段。

    Foo& foo;

但是当您尝试分配给它时,这会导致错误。为此,我们要使用一种特殊的构造函数初始化语法。它基本上与赋值相同,但执行构造而不是正常赋值。所以写你的构造函数如下。

    Bar(Foo& foo) : foo(foo) {}

您还必须完全删除默认构造函数 Bar(),因为大多数 C++ 编译器会拒绝可能导致未初始化引用的代码。