char*[]
对象可以传递给函数version2()& const引用的版本3(),这意味着s2是一个临时对象,等于“###”或“@@@”。
但为什么临时对象 s2 可以返回,而临时对象temp 则不能。
int main()
{
result = version2(input, "###");
cout << "Your string enhanced: " << result << endl;
result = version3(input, "@@@");
cout << "Your string enhanced: " << result << endl;
return 0;
}
// No Error
const string & version2(string & s1, const string & s2)
{
return s2;
}
// Error
const string & version3(string & s1, const string & s2)
{
string temp = s2 + s1 + s2;
return temp;
}
答案 0 :(得分:3)
重点是object life time。
对于第一种情况,正如您所说,创建了一个临时std::string
并传递给version2
(绑定到参数s2
)。在完整表达之后,临时将被销毁,即整个result = version2(input, "###");
。这意味着version2
返回的引用仍然有效,可以将其用于分配给result
。
所有临时对象都被销毁,作为评估(词法上)包含创建它们的点的完整表达式的最后一步,
对于第二种情况,在temp
内创建了一个本地对象version3
,它将在离开version3
时被销毁。这意味着version3
将始终返回悬空参考。并使用它分配给result
导致UB。编译器可能会对其进行诊断;但并非必须这样做。
答案 1 :(得分:0)
两个版本都返回对象的引用。
version2
从main获得了一个引用并将其恢复为未修改。
version3
定义了一个局部变量temp
,并希望返回对该局部的引用。但不幸的是,一旦你从version3
返回,本地就不再存在了。因此,您将返回一个已经被销毁的引用。
答案 2 :(得分:0)
我之所以这么说,只是因为编译器并不认为version2
是危险的。
请注意,对于version3
,它实际上会发出警告,而不是错误(除非您告诉它)。
事实上,如果你改变它以通过引用来捕获结果,那么仍然没有警告,但临时无疑已被破坏。你可以检查组件(或标准),但在这里我重现它并使其易于观察。 (虽然这将取决于编译器)
如果您切换优化,您可以看到输出更改,并且没有给出任何警告。
以防万一,这是测试代码
#include<string>
#include<iostream>
using namespace std;
// No Error
auto& f(const string & s){return s;}
int main()
{
char s[]="#";
const char* cs = s;
auto& x = f(cs);
s[0]='o';
[[maybe_unused]] auto& y = f(cs);
cout << x;
}
g++7.2 -Wall -Wextra -std=c++17