作为一个新手,我发现在C ++书籍中从函数返回的解释相当神秘。
以下是我理解的摘要,希望有人能够纠正它:
前提:
T foo() {
...
return expr;
}
main() {
T var = foo();
}
我对回归过程的理解是否正确?
expr
的评估结果被隐式转换为声明的函数返回类型T
。此转换发生在 foo(); var
。 欢迎任何输入!
答案 0 :(得分:6)
让我们系统地解决这个问题。
如果函数声明为T f();
,而T
不是void
,并且函数正常返回,则它必须通过{{1}形式的语句返回},其中return e;
是表达式。
当您评估函数调用表达式e
时,您将获得一个值。假设f()
表示对象类型。如果U
或T = U &
,则值为T = U &&
,则表达式U
必须能够绑定到引用,并且返回值为< / em> e
的值。 (返回值也是所谓的&#34; glvalue&#34;,就其价值类别而言)。在这种情况下没有其他事情发生。函数调用的值是返回的东西。
然而,当e
时,T = U
的值是所谓的&#34; prvalue&#34; (a&#34;纯rvalue&#34;),这需要构建f()
类型的临时对象。该对象的构造就像U
一样(即从U obj = e
隐式转换)。 e
的值就是这个临时对象。它可以用于初始化另一个对象(例如f()
),也可以绑定到引用(例如U x = f();
)。
返回表达式U && r = f();
与函数调用值的绑定是函数体范围内的最后一件事。值得注意的是,这是在范围结束之前,即在范围本地对象被销毁之前。例如,如果在构造返回值对象期间抛出异常,则在异常传递给调用范围之前,必须发生范围展开以销毁本地对象。另一个有用的例子可能是使用范围防护装置,例如:互斥锁:
e
我们假设初始化U f()
{
std::locK_guard<std::mutex> lock(state_mutex);
return state.get_value();
}
有意义,我们进一步假设U obj = state.get_value();
只能在state.get_value()
被锁定时调用。上面的代码正确而简洁地做到了这一点。
答案 1 :(得分:4)
foo
内。考虑当你有多个return
语句并且每个语句返回不同的类型时 - 必须先转换所有这些类型,然后才能返回一个值。许多编译器都会进行优化,称为copy elision,它会完全跳过临时文件。
答案 2 :(得分:2)
您的理解基本上是正确的。
可以有一些优化,因此没有那么多的步骤
复制。这可以是return value optimization
或
的形式
在c ++ 11中move semantics
关于你的子问题;
在自定义转换运算符,构造函数中,您应该不假设
析构者等。