【问题标题】:Is this C++ reference assignment correct?这个 C++ 引用赋值正确吗?
【发布时间】:2013-02-01 17:35:44
【问题描述】:

在这个简化的示例中,我的问题是:我是否在 Action::setUser() 中进行合法分配?

class User {
private:
   int age;
public:
   int getAge() { return age; }
};

class Action {
private:
   User user;
public:
   void setUser(User &u) {
      user = u;
   }
};

int main() {
   User u;
   Action a;
   a.setUser(u);
   return 0;
}

让我吵闹的是,

  • 当调用 setUser 时,Action 的“用户”属性会发生什么变化?它被摧毁了吗?它曾经建造过吗?
  • 如果我第二次调用 setUser 会发生什么?
  • 如果我删除 setUser 中的“&”符号,一切都会好起来的,对吧?因为这就像传递参数的副本,对吧?

我担心我在用内存做疯狂的事情,因为属性没有被正确地破坏......

谢谢


于 2013 年 2 月 18 日星期一编辑

非常感谢!我非常感谢您的所有回复...

我不知道编译器提供了默认的重载赋值运算符。现在我知道一切都说得通了……

再次感谢。

【问题讨论】:

  • 除了const User& u 可能会更好之外,分配还不错。它会在没有中间副本的情况下将用户复制到 by-val 参数。 Action 的现有用户不会被销毁setUser(u),而是会通过赋值运算符“覆盖”。如果您愿意,您可以通过自己编写User::operator =(const User& u) 来控制如何完成。关于第二个电话,与第一个电话相同。最后,删除 & 引入至少一个额外的副本。
  • 我想知道你写的最后一句话:“我担心我在用内存做疯狂的事情,因为属性没有被正确销毁” - 你是什么意思通过“被正确销毁”?您如何看待这个问题?

标签: c++ reference variable-assignment


【解决方案1】:

调用 setUser 时,Action 的“用户”属性会发生什么变化?

赋值运算符(由编译器提供,因为您尚未定义自定义运算符)被调用,它只是执行从uuser 的成员方式复制。

它被摧毁了吗?

没有。

它曾经建造过吗?

是的。

如果我第二次调用 setUser 会发生什么?

同样的事情。

如果我删除 setUser 中的“&”符号,一切都会好起来的,对吧?

就分配给user 而言,这没有任何区别。通过引用传递只是意味着在调用函数时不会复制参数。

【讨论】:

    【解决方案2】:

    是的,没关系。它只是将您在 main 中定义的u 直接分配给a.user。引用参数避免制作额外的副本以传递给a.setUser

    当您创建一个Action 时,它包含一个默认构造的User 对象。然后,您为该User 分配一个值。这不是 (IMO) 最好的设计(我宁愿看到 User 使用正确的值构造)但它完全有效。

    赋值不会创建或破坏现有值。 Action 对象将在超出范围时被销毁,这将销毁它包含的 User 对象。

    【讨论】:

      【解决方案3】:

      答案:

      • 它没有被破坏,而是被覆盖(复制分配)。是的,它是以前建造的。
      • 和第一次一样。
      • 如果您删除了&,您将传递一个副本。但它不会使事情变得错误或正确。

      注意事项:

      • 在成员函数和传递的参数上都使用 const。
      • 您至少需要考虑控制复制和分配。这应该在任何更好的 C++ 介绍或常见问题解答中解释。

      【讨论】:

        【解决方案4】:
        class Action {
        private:
           User user;
        }
        

        定义User 类型的私有成员。它是一个具有自动存储持续时间的对象,它是在构造 Action 类型的对象时构造的。它的生命周期与 Action 类型的对象的生命周期相关。

        现在在这个方法中:

        void setUser(User &u) {
            user = u;
        }
        

        u 是对其属性(成员)的对象的引用,该对象的属性(成员)将用于使用 赋值运算符设置user 的属性。

        如果您在此处删除&,您将通过引用将传递更改为按值传递,这意味着传递给此方法的对象副本将在其调用时创建。

        【讨论】:

          猜你喜欢
          • 2020-02-09
          • 2018-01-12
          • 1970-01-01
          • 1970-01-01
          • 2023-04-06
          • 1970-01-01
          • 2011-04-25
          • 2013-04-02
          • 2011-05-26
          相关资源
          最近更新 更多