C ++:返回值是L值吗?

时间:2011-05-24 14:21:01

标签: c++ return-value lvalue

考虑以下代码:

struct foo
{
  int a;
};

foo q() { foo f; f.a =4; return f;}

int main()
{
  foo i;
  i.a = 5;
  q() = i;
}

没有编译器抱怨它,甚至Clang。为什么q() = ...行是正确的?

3 个答案:

答案 0 :(得分:66)

不,当且仅当它是引用时,函数的返回值才是l值(C ++ 03)。 (5.2.2 [expr.call] / 10)

如果返回的类型是基本类型,那么这将是编译错误。 (5.17 [expr.ass] / 1)

这样做的原因是你可以在类类型的r值上调用成员函数(甚至是非const成员函数),并且foo的赋值是一个实现定义的成员功能:foo& foo::operator=(const foo&)。第5节中对运算符的限制仅适用于内置运算符,(5 [expr] / 3),如果重载决策为运算符选择了重载函数调用,则该函数调用的限制适用代替。

这就是为什么有时建议将类类型的对象作为const对象返回(例如const foo q();),但这会对C ++ 0x产生负面影响,因为它可以抑制移动语义从他们应该的工作。

答案 1 :(得分:8)

因为结构可以分配给,q()返回struct foo的副本,所以它将返回的结构分配给提供的值。

在这种情况下,这并没有真正做任何事情,因为结构在之后超出了范围,并且你没有首先对它进行引用,所以你无论如何也无法对它做任何事情(在这个特定的情况下)码)。

这更有意义(尽管仍然不是真正的“最佳实践”)

struct foo
{
  int a;
};

foo* q() { foo *f = new malloc(sizeof(foo)); f->a = 4; return f; }

int main()
{
  foo i;
  i.a = 5;

  //sets the contents of the newly created foo
  //to the contents of your i variable
  (*(q())) = i;
}

答案 2 :(得分:6)

这是一个有趣的应用:

void f(const std::string& x);
std::string g() { return "<tag>"; }

...

f(g() += "</tag>");

此处,g() +=修改临时值,这可能比使用+创建额外临时值更快,因为为g()的返回值分配的堆可能已经有足够的备用容量来容纳</tag> {1}}。

看到它运行at ideone.com with GCC / C++11

现在,哪位计算新手说了一些关于优化和邪恶的事情......? ; - ]