引用临时对象的析构函数

4

给出的例子:

#include <iostream>

#include <cstdlib>

#define PRINT_NAME { std::cout << __PRETTY_FUNCTION__ << std::endl; }

namespace
{

struct A 
{
    A() { PRINT_NAME; }
    ~A() { PRINT_NAME; }
};

A f() { return {}; }

A b;

A && g() { return std::move(b); }

}

int
main()
{ 
    std::cout << "------------------" << std::endl;
    {
        f();
        std::cout << 1 << std::endl;
    }
    std::cout << "------------------" << std::endl;
    {
        A && a = f();
        // or A const & a = f(); as mentioned in below discussion
        std::cout << 2 << std::endl;
    }
    std::cout << "------------------" << std::endl;
    {
        A && a = g();
        std::cout << 3 << std::endl;
    }
    std::cout << "------------------" << std::endl;
    return EXIT_SUCCESS;
}

以及它的输出 (clang 3.5.0):

(anonymous namespace)::A::A()
------------------
(anonymous namespace)::A::A()
(anonymous namespace)::A::~A()
1
------------------
(anonymous namespace)::A::A()
2
(anonymous namespace)::A::~A()
------------------
3
------------------
(anonymous namespace)::A::~A()

什么是语义规则?它是标准段落的可想象的简写形式,紧凑地概括了有关上述代码示例中析构函数行为的差异。我经常面对由“具有某些(非明显相关)特征”或“具有某些固有属性”的声明所制定的“惯用规则”,例如,“如果它有一个名称,则它是一个左值”。是否有类似的东西?

在生命周期方面,将一个rvalue引用绑定到一个const lvalue引用没有任何区别。 - T.C.
@T.C. 真的是这样。对我来说不明显。如果问题没有意义,那我很抱歉。 - Tomilov Anatoliy
1
标准的第12.2/5段。 - n. m.
@n.m. 正是我想要的(似乎无法压缩)。 - Tomilov Anatoliy
1个回答

4
这与右值引用无关。实际上,如果你将代码中的A&&更改为const A&行为不会改变
可能你的困惑是由于std::move()函数的名称造成的。它实际上并不移动任何东西,只是将其参数转换为右值引用。
不要考虑析构函数,而要考虑对象的生存期。个人认为没有简单的经验法则(除了“阅读标准”),但这三条规则可能会帮助你:
  1. 静态对象的生命周期基本上是整个程序的 生命周期。
  2. 如果从函数返回的临时对象未绑定到任何内容,则在整个表达式执行完成后,其生命周期结束。
  3. 如果从函数返回的临时对象绑定到一些引用,则其生存期延长到该引用的生命周期。

关于第三个条件语句:如果我修改代码 A && g() { A && c = f(); return std::move(c); } 那么在 } 括号处会调用 c.~A()。但是临时对象的引用仍然存在。 - Tomilov Anatoliy
因为在这种情况下,对象会在g()结束时被销毁(因此返回一个悬空引用),所以要使用@Orient。 - Anton Savin
你对因果关系感到困惑。更确切地说,你提到的效果与我的问题无关。我只是想告诉你,第三个条款定义不清,可能会引起混淆(因为它并不适用于每种情况,当临时对象绑定到任何引用时,而仅适用于特定情况)。 - Tomilov Anatoliy
@Orient 在第一个从句中,未绑定的临时对象会立即被销毁。在第二个从句中,临时对象被绑定到引用上,因此其生命周期得以延长。在第三个从句中,你只是引用了一个静态对象。那么我提到的和你问题无关的内容是什么呢? - Anton Savin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接