【问题标题】:Returning *this with an assignment operator使用赋值运算符返回 *this
【发布时间】:2011-03-15 23:26:40
【问题描述】:

我重新创建了自己的复制构造函数,总体上对我来说很有意义。然而,关于做你自己的赋值运算符的话题,我需要有人帮我填空。

我几乎不明白您为什么在所有示例中都返回 *this,例如以下示例:

Foo & Foo::operator=(const Foo & f)
{

//some logic

return *this;

}

所以如果我有一些类似的陈述:

Foo f;
f.hour = 7;

Foo g;
g = f;

一旦赋值运算符运行,它就会返回对 g 对象的引用(*this)。所以现在的问题是,我现在不会有这样一个隐含的声明吗?:

g = g (g being a reference)

问题是,在此之前,仅设置对对象的引用会导致调用复制构造函数。在这种情况下,它不符合复制构造函数的签名。

【问题讨论】:

  • @In silico:或者,编写您的赋值运算符,以便它们可以使用自赋值(这通常是具有异常安全赋值运算符的结果)。
  • 我的问题甚至超出 *this 是:如果我返回一个对象的引用并将其存储到一个普通对象中,如果不调用复制构造函数会发生什么。就我而言,我已经写好了赋值运算符,所以不会调用复制构造函数。
  • 查找用于实现赋值运算符的复制交换 idium。它是异常安全的,意味着您不需要显式检查对 self 的分配(除非您也想要)。

标签: c++


【解决方案1】:

你想返回*this,这样你就可以链接=

Foo f, g, h;

f = g = h;

这基本上是将h分配给g,然后将g(由return *this返回)分配给f

f = (g = h);

有时使用的另一种情况是有条件的赋值(被许多人认为是不好的风格):

if ( (f = 3).isOK() ) {

使用g = f; 语句,返回将被忽略,就像您执行3 + 4; 一样。

【讨论】:

  • 或者更经典的例子((f = func_returning_f()) != f_to_ignore)
【解决方案2】:

我认为您有点混淆了中缀表示法的概念。 g = f 并不意味着 call operator= of g with f and put the result into g 它意味着 apply operator= on g with parameter f and set the value of this expression to the result。这与 +/ 等其他中缀运算符的行为相同。

某些语言中的运算符可以像普通函数一样应用(在 C++ 中使用一些无关的语法),例如 = (g f),它更清楚地显示了这个概念。

编辑:

比如IO常用的例子:

// loop until some sentinel value
while ((nextChar = (char) getchar()) != 'Q') {
  string += nextChar;
}

请注意,由于 = 运算符返回其第一个参数(本示例中为 nextChar),您可以组合赋值和测试。

【讨论】:

    【解决方案3】:

    一旦赋值运算符运行,它 返回对 g 对象的引用 (*这个)。所以现在的问题是, 我现在不会有一个声明吗 隐含的像这样?:

    g = g(g 为参考)

    不,但是您需要检查自我分配。返回*this 所做的是使表达式(g=f)g 的值。这对于链接分配很有用。在像

    这样的声明中
    Foo a, b, c;
    a = b = c;
    

    a 被分配了来自方法 operator= 的返回值。返回 *this 使该语句执行预期的操作(将 c 的值分配给 b,然后将 b 的新值分配给 a)。

    【讨论】:

      【解决方案4】:

      原因是你的赋值结果可以是另一个表达式中的右值。

      【讨论】:

      • 调用返回引用的函数实际上是一个左值
      • @FredOverflow:如果 f 是返回引用的函数,则 f()=5 使用 f() 作为左值。但是 a=f(); 呢?这是使用 f() 结果作为右值吗? a = b = c 类似于 a = (b = c),类似于 a = f()
      • 您已链接到一个 C 问题,但术语 lvaluervalue 在 C 和 C++ 中具有不同的含义。 (实际上,在当前的 C 标准中并没有“右值”这样的东西。)
      • @FredOverflow:这个问题/接受的答案表明您不正确:stackoverflow.com/questions/2038414/lvalue-and-rvalue。不过,我认为,这个问题促使我确保我对什么是左值和右值有一个好的+可靠的定义(从这个评论中的答案来看,对我来说仍然很模糊)。
      • @curiousguy:首先,C 标准甚至没有定义术语“右值”。标准 C 只知道左值。但是让我们假设 C 有右值。这里有两个例子: 1. 在 C++ 中计算 struct 类型的右值会产生一个临时对象,它的生命周期是明确定义的(“完整表达式结束”)。在 C 中,情况并非如此。我偶然发现了这个two months ago。 2.在C中不可能赋值给右值。在C++中,你可以说std::string("hello") = "world";没有问题,而std::string("hello")是一个右值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-05
      • 2019-12-29
      • 1970-01-01
      • 2015-07-16
      • 2015-04-10
      相关资源
      最近更新 更多