【问题标题】:Why does "return *this" return a reference?为什么“return *this”会返回一个引用?
【发布时间】:2012-01-28 20:34:11
【问题描述】:

在我的 C++ 课程中,他们正在讨论如何创建赋值运算符。在分配的最后是“return *this”行,他们说它返回了对“this”指向的对象的引用。为什么它返回一个引用?如果“this”被取消引用,它不应该只返回对象吗?

【问题讨论】:

  • 我不确定...但很可能您的返回类型类似于“int&”而不是简单的“int”,您注意到了吗?

标签: c++


【解决方案1】:

如果函数的声明(即它的签名)告诉我们,函数会返回一个引用。

所以(假设是class Foo)如果声明了一个函数

 Foo fun();

然后它返回一个值(复制等)

但是如果声明为

 Foo& fun();

或作为

 const Foo& fun();

返回一个引用。

语句return *this; 不自行定义是否返回引用或值。

【讨论】:

  • 好的,有道理,谢谢!我不知道你能做到。
【解决方案2】:

它返回您所在类型 MyClass 的当前实例。它作为引用返回,因为赋值运算符被明确告知要返回一个引用。

MyClass& operator = (MyClass& other)  { return *this; }

注意 MyClass 后面的 & 作为返回值。返回一个引用。 除非&operator 之前不存在,否则实例将按值返回。

【讨论】:

  • 这似乎是一个循环的答案。问题中没有显示代码;我们只是被告知了一个返回引用的函数。被问到的是“为什么?”演示具有引用返回类型的随机函数似乎并未涵盖这一点。
  • @LightnessRacesinOrbit 我认为这个问题用一个例子描述得很好,我很确定他的书使用了类似的功能。如果它不是一个明确的答案,请纠正我:)。
  • 我对你的问题有不同的解释。您似乎已将其读作“在代码中是什么让我的函数返回引用?”这个问题的最后一句话让我觉得这不太可能。
【解决方案3】:

表达式*this

在赋值的最后一行是“return *this”,他们说它返回了对“this”指向的对象的引用

他们错了。

为什么它返回一个引用?

没有。

如果“this”被取消引用,它不应该只返回对象吗?

是的!

取消引用指针会产生一个左值。这意味着*this 的结果是this 指向的实际对象。这不是参考,但也不是副本。

[C++11: 5.3.1/1]: 一元 * 运算符执行间接:应用它的表达式应该是一个指向对象类型的指针,或者是一个指向函数类型的指针,结果是一个左值,指向表达式指向的对象或函数。 如果表达式的类型是“指向T 的指针”,则结果的类型是“T”。 [..]

这可能很难概念化,因为您永远无法在代码中自己做到这一点;它只是用于本地指针的 * 运算符的一个功能,并且自 C 以来一直存在。


operator=返回

因为你不能自己做,通常你会将该 lvalue 表达式绑定到一个引用,以便在不同的上下文中使用它。例如,return *this 中的表达式 *this 绑定到您要从中返回的函数的返回类型;在这种情况下,一个赋值运算符。

现在,我们可以让赋值运算符按值返回,在这种情况下,将从来自*this 的左值复制一个对象;但是,对于赋值运算符,我们通常通过引用返回,这样我们就可以避免几乎肯定不必要的复制,并且可以执行链接

Type a, b, c;
c = b = a;

这是一个有好处的约定,没有坏处。你能想出一个你希望op=按值返回的情况吗?

【讨论】:

  • 谢谢,第一个帖子说l-value! +1
【解决方案4】:

每个取消引用的指针都是对其指针对象的引用,否则您将“松散”您所指向的指针对象。

在同一个对象上调用方法两次,使用指针和引用:

MyClass* objPtr = .... ;
objPtr->doSomething();
MyClass& objRef = *objPtr;
objRef.doSomething();

在不同的对象上调用方法;原件和复印件:

MyClass* objPtr = .... ;
objPtr->doSomething();
MyClass objCopy = *objPtr; //here, the reference is passed to the (implicit or implemented) copy constructor if possible, else a compile time error occurs.
objCopy.doSomething();

这意味着,如果您从具有 MyClass (rvalue) 而不是 MyClass& (lvalue) 作为返回类型的运算符方法返回引用,则 *this (MyClass&) 的副本是通过引用创建的(撇开返回值优化和右值引用)。 这对于非修改 const 方法(例如 + 和 -)很有用,它们具有新值作为结果,同时保持调用此方法的对象不被修改。

像 += 这样的操作符和你的赋值操作符按照约定在原地修改对象,因此应该返回一个引用以允许像原始类型这样的表达式支持它,因为临时副本可能会消失并导致意外结果:

考虑这个表达式:

int i = 4;
int r = (i += 3) <<= 2;

结果 r 为 28(相加并就地移位)。 我的价值是多少? 28也是,还有什么。

但是如果假设 int::operator+= 会返回自身的副本而不是对自身的引用呢?

结果 r 也是 28。

但是 i 的值呢? 它将是 7,因为就地左移被应用于从加法返回的临时 int,然后分配给 r。

继续假设,错误可能与此表达式具有相同的效果(i中的值除外):

int r = (i + 3) <<= 2;

但幸运的是,编译器会抱怨,他没有来自 (i + 3) 的左值引用来执行移位/赋值操作。

但是玩这个:

class Int
{
private:
    int val;
public:
    Int(int val) :
            val(val)
    {
    }

    Int operator+(const Int& other)const
    {
        return val + other.val;
    }
    Int operator+(int prim)const
    {
        return val + prim;
    }

    Int& operator+=(const Int& other)
    {
        val += other.val;
        return *this;
    }
    //Error here, Int& would be correct
    Int operator+=(int prim)
    {
        val += prim;
        return *this;
    }

    Int operator<<(const Int& other)const
    {
        return val << other.val;
    }
    Int operator<<(int prim)const
    {
        return val << prim;
    }

    Int& operator<<=(const Int& other)
    {
        val <<= other.val;
        return *this;
    }
    Int& operator<<=(int prim)
    {
        val <<= prim;
        return *this;
    }

    operator int()const{
        return val;
    }
};

int main()
{
    Int i = 4;
    Int r = (i += 3) <<= 2;

    cout << i;
    return 0;
}

【讨论】:

    【解决方案5】:

    在 C++ 中,* 总是表示一个值,实际上您可以查看这些运算符的英文解释如下:

    &amp;:地址

    *: 的值

    所以当您说&amp;x 时,它的意思是“x 的地址”,而当您说*x 时,它的意思是“x 指向的值”。所以*this 总是会返回一个值。

    只要确保返回的函数本身不是引用函数。请记住,在 C++ 中,您也可以使用 & 或 * 运算符创建函数。

    【讨论】:

      猜你喜欢
      • 2014-10-08
      • 2018-06-26
      • 2011-08-03
      • 1970-01-01
      • 2022-11-16
      • 2016-04-06
      • 2011-05-22
      • 2014-04-24
      • 1970-01-01
      相关资源
      最近更新 更多