Joh*_*ohn 71 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;
}
Run Code Online (Sandbox Code Playgroud)
没有编译器抱怨它,甚至Clang.为什么q() = ...线路正确?
CB *_*ley 66
不,当且仅当它是引用时,函数的返回值才是l值(C++ 03).(5.2.2 [expr.call]/10)
如果返回的类型是基本类型,那么这将是编译错误.(5.17 [expr.ass]/1)
这样做的原因是你可以在const类类型的r值上调用成员函数(甚至是非成员函数),并且赋值foo是一个实现定义的成员函数:foo& foo::operator=(const foo&).第5节中对运算符的限制仅适用于内置运算符(5 [expr]/3),如果重载决策为运算符选择了重载函数调用,则应用该函数调用的限制.
这就是为什么有时会建议将类类型的const对象作为对象返回(例如const foo q();),但是这会对C++ 0x产生负面影响,因为它可以抑制移动语义不能正常工作.
因为结构可以分配给,并且您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;
}
Run Code Online (Sandbox Code Playgroud)
一个有趣的应用:
void f(const std::string& x);
std::string g() { return "<tag>"; }
...
f(g() += "</tag>");
Run Code Online (Sandbox Code Playgroud)
在这里,g() +=修改临时,这可能比创建一个额外的临时更快,+因为为g()的返回值分配的堆可能已经有足够的备用容量来容纳</tag>.
通过GCC/C++ 11查看它在ideone.com上的运行情况.
现在,哪位计算新手说了一些关于优化和邪恶的东西......?; - ].