考虑以下代码:
struct foo
{
int a;
};
foo q() { foo f; f.a =4; return f;}
int main()
{
foo i;
i.a = 5;
q() = i;
}
没有编译器抱怨它,甚至Clang。为什么q() = ...
行是正确的?
答案 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。
现在,哪位计算新手说了一些关于优化和邪恶的事情......? ; - ]