为什么在此示例中可以返回临时对象?

时间:2018-03-30 08:18:56

标签: c++ pass-by-reference temporary-objects

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;
}

3 个答案:

答案 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,它实际上会发出警告,而不是错误(除非您告诉它)。

事实上,如果你改变它以通过引用来捕获结果,那么仍然没有警告,但临时无疑已被破坏。你可以检查组件(或标准),但在这里我重现它并使其易于观察。 (虽然这将取决于编译器)

wandbox example

如果您切换优化,您可以看到输出更改,并且没有给出任何警告。

以防万一,这是测试代码

#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