问题描述
|
考虑以下代码:
struct foo
{
int a;
};
foo q() { foo f; f.a =4; return f;}
int main()
{
foo i;
i.a = 5;
q() = i;
}
没有编译器抱怨它,即使是Clang。为什么q() = ...
线是正确的?
解决方法
不,当且仅当它是引用时,函数的返回值才是L值(C ++ 03)。 (5.2.2 [expr.call] / 10)
如果返回的类型是基本类型,则将是编译错误。 (5.17 [expr.ass] / 1)
之所以可行,是因为允许您在类类型的r值上调用成员函数(甚至是非“ 2”成员函数),“ 3”的赋值是实现定义的成员函数:“ 4”。第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;
}
,一个有趣的应用程序:
void f(const std::string& x);
std::string g() { return \"<tag>\"; }
...
f(g() += \"</tag>\");
在这里,g() +=
修改了临时项,这可能比用+
创建另一个临时项更快,因为分配给g()返回值的堆可能已经有足够的备用容量来容纳</tag>
。
看到它运行在ideone.com上,带有GCC / C ++ 11。
现在,哪个计算新手谈到了优化和邪恶……? ;-]。