C ++:返回值是一个L值?
考虑这个代码:
struct foo { int a; }; foo q() { foo f; fa =4; return f;} int main() { foo i; ia = 5; q() = i; }
没有编译器抱怨,即使是Clang。 为什么q() = ...
行是正确的?
不,当且仅当它是一个引用(C ++ 03)时,函数的返回值是一个l值。 (5.2.2 [expr.call] / 10)
如果返回的types是基本types,那么这将是一个编译错误。 (5.17 [expr.ass] / 1)
这样做的原因是,你可以调用成员函数(甚至是非const
成员函数)的类types的r值,而赋值foo
是一个实现定义的成员函数: foo& foo::operator=(const foo&)
。 第5章中对运算符的限制仅适用于内置运算符 (5 [expr] / 3),如果重载决策为运算符select了重载函数调用,则应用该函数调用的限制。
这就是为什么有时候推荐将类types的对象作为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; ia = 5; //sets the contents of the newly created foo //to the contents of your i variable (*(q())) = i; }
一个有趣的应用是:
void f(const std::string& x); std::string g() { return "<tag>"; } ... f(g() += "</tag>");
在这里, g() +=
修改临时的,这可能会更快,创build一个额外的临时+
因为分配给g()的返回值的堆可能已经有足够的备用容量来容纳</tag>
。
看到它运行在ideone.com与GCC / C + + 11 。
现在,哪个计算新手说了一些关于优化和邪恶的东西? ; – ]。