C++ - 需要左值作为赋值运算符的左操作数

4

考虑以下代码:

#include <iostream>
using namespace std;

class X 
{
    int i;
public:  
    X(int ii = 0);
};

X::X(int ii) { i = ii; }

int a;

X f1() { return X(); }
int f2() { return a; }

int main() {
    f1() = X(1);
    f2() = 3;
} 

如果你试图运行它,你会得到:

错误: 赋值的左边必须是一个可修改的 lvalue

在第17行,因此

f1()

被认为是一个lvalue,而

f2()

则不是。如何工作的解释将会非常有帮助。


1
f1() 不是左值因为 f1 返回一份副本。阅读 http://en.cppreference.com/w/cpp/language/value_category 了解更多移动信息。 - Sajad Banooie
1
希望你明白为什么不能给临时的 int 赋值,如果不明白,我会再添加一个重复说明。 - Baum mit Augen
@Baum mit Augen 我很好,谢谢。 - George Cernat
2个回答

5

f1() 被认为是一个左值。

不,f1 返回的仍然是右值(与 f2 相同;更准确地说,它是一个 prvalue)。但对于类类型,f1() = X(1); 只被解释为 f1().operator=(X(1));,这非常好,尽管它可能没有多少意义;由 f1() 返回的临时对象将很快被销毁。简而言之,您可以在具有类类型的右值上调用成员函数。

另一方面,内置类型的类似行为直接被禁止;对这种临时变量的赋值根本没有意义。这就是为什么编译器会抱怨它不是左值的原因。


3

f1() 返回一个右值。你需要返回一个引用(左值)以允许你进行此赋值操作。

更改为:

int f2() { return a; }

int& f2() {  return a; }
   ^

f1()返回一个rvalue,但是像f1() = X(1);这样的调用会调用类的赋值运算符f1().operator=(X(1));,这是可以的。

在此处阅读更多关于值类别的信息。


“如何使其工作”并不是问题。 - Baum mit Augen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接