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

时间:2017-05-21 16:40:28

标签: c++ oop pass-by-reference

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

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
}

3 个答案:

答案 0 :(得分:3)

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

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

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

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

(请注意我必须使用the member initialization list syntax因为引用cannot be default-initialized and then reseated

答案 1 :(得分:0)

您将对foo的引用传递给bar的构造函数,但随后通过引用bar.foo分配(复制)您传递的foo。

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

答案 2 :(得分:0)

问题出在这里。

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

即使您通过引用获取foo参数,也可以将其分配给非参考值,从而生成副本并解决您提出的问题。解决方案的第一步是通过引用声明您的实例字段。

    Foo& foo;

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

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

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