考虑下面的代码:
struct foo { int a; }; foo q() { foo f; f.a =4; return f;} int main() { foo i; i.a = 5; q() = i; }
没有编译器抱怨它,甚至 Clang。为什么 q() = ...行是正确的?
q() = ...
因为结构可以被赋值,并且您的 q()返回 struct foo的副本,所以它将返回的结构赋给所提供的值。
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; }
不,函数的返回值是一个 l- 值当且仅当它是一个引用(C + + 03)。(5.2.2[ expr.call ]/10)
如果返回的类型是基本类型,那么这将是一个编译错误
这样做的原因是允许对类类型的 r 值调用成员函数(甚至非 const成员函数) ,并且 foo的赋值是一个实现定义的成员函数: foo& foo::operator=(const foo&)。子句5中对于操作符的限制只适用于 内置操作系统(5[ expr ]/3) ,如果重载解析为操作符选择了一个重载函数调用,那么对于该函数调用的限制将改为适用。
const
foo
foo& foo::operator=(const foo&)
这就是为什么有时候建议将类类型的对象作为 const对象(例如 const foo q();)返回,但是在 C + + 0x 中这可能会产生负面影响,因为它会抑制 move 语义的工作。
const foo q();
一个有趣的应用是:
void f(const std::string& x); std::string g() { return "<tag>"; } ... f(g() += "</tag>");
在这里,g() +=修改临时数据,这可能比用 +创建额外的临时数据更快,因为为 g ()的返回值分配的堆可能已经有足够的空闲容量来容纳 </tag>。
g() +=
+
</tag>
运行 在 ideone.com 和 GCC/C + + 11一起。
现在,哪个计算新手说过关于优化和邪恶的东西... ? ;-]。
在其他好的答案之上,我想指出的是,std::tie在这种机制之上工作,从另一个函数解包数据。看这里.所以它本身并不容易出错,只要记住它可能是一个有用的设计模式
std::tie