C ++:返回时对象不会被解构?

时间:2017-12-11 02:42:57

标签: c++

有一天,我想知道返回字符串对象时是否有内存副本。但是,我觉得很奇怪。当我在函数中返回一个对象时,我希望有一个复制结构来创建一个临时对象作为返回值。所以,我尝试以下代码。

class Substring: public string
{
public:
    Substring(const char* s)
    :string(s)
    {
    }

    ~Substring()
    {
        cout << "Deconstruct" << endl;
    }
};

Substring foo()
{
    Substring ret("test");
    printf("Inner address: %p\n", ret.c_str());
    return ret;
}

int main()
{
    Substring test = foo();
    printf("Return address: %p\n", test.c_str());
    return 0;
}

正如我所说,我期待Return addressInner address不同。并且Deconstruct应该在Inner address

之后打印出来

这就是我得到的。当外部变量ret死亡时,似乎解构test,而不是超出其范围的时间!为什么呢?

Inner address: 0x7ffed3a4cb40
Return address: 0x7ffed3a4cb40
Deconstruct

1 个答案:

答案 0 :(得分:1)

C ++有这个叫做elision的东西。

多个对象可以将它们的生命时间省略在一起。这意味着乍一看有3个子串对象(rettest和匿名返回值),在省略后,它们都是同一个对象,只有一个构造和破坏。

对于elision有各种限制(标准强制和实用),并且某些形式被强制执行。

特别是,几乎总是允许删除prvalue,如果在C ++ 17中几乎总是允许的话。

如果return语句为return var_name;并且类型匹配,则可以使用prvalues省略命名变量,并使用命名的locals返回值。

人们为特定种类的精灵 - RVO和NRVO - 制作了名称 - 但我觉得它们比启发更令人困惑。

禁用elision是一个坏主意,必须这样做表明你的对象模型与C ++的假设不同。