c++ 为什么两次调用std::any析构函数?

aij0ehis  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(69)

此问题在此处已有答案

Destructor called unexpectedly(1个答案)
What is The Rule of Three?(8个回答)
7天前关闭
出于好奇:我在代码库中使用类型擦除,然后我注意到对象的析构函数被调用两次。
我用std::any简化了它,甚至用std::any,析构函数被调用两次:
https://godbolt.org/z/jaEqq7Psa

struct foo 
{
    foo() {std::cout << "ctor\n"; }
    ~foo() {std::cout << "dtor\n"; }
};

int main() 
{    
    std::any any_foo = foo{}; 
    return 0;
}

字符串
我已经做了同样的例子,考虑到5的规则,有一个移动构造函数一旦被调用,我玩了一下,但我不能消除多个析构函数调用。

dgsult0t

dgsult0t1#

有一个移动构造函数,
这应该是一个明显的线索,表明您正在处理多个对象。
在格式良好和定义良好的代码中,每个构造的对象在某个时候都会被销毁。这是C的基础。
一个移动构造函数并没有改变这个规则。移动构造函数本身就是一个构造函数。所以它构造了一个对象。但是moved-from对象也必须在某个时候被构造。所以现在至少有两个对象在某个时候会被销毁。moved-from对象仍然是一个在某个时候被构造的C
对象。所以它必须被销毁,在某些时候。即使在某些时候,它是moved-from,这也是真的。移动操作所做的就是让moved-from对象处于某种“有效,但未指定”的状态。它仍然是一个有效的对象。它会被销毁。

std::any any_foo = foo{};

字符串
首先,一个临时的foo对象被创建。然后std::any被构造,并吞下这个foo。然而,std::any不能通过渗透吸收其他对象。std::any唯一能做的就是复制/移动它所拥有的另一个foo。这就是你看到的移动构造函数被调用的地方。
最后,临时的foo被销毁。然后,std::any被销毁,它的析构函数也销毁了它拥有的foo。这是第二个析构函数调用。
在这里,std::any有它自己的对象,无论它是什么对象,它都拥有它。它不能接管已经构造的另一个对象的所有权。

相关问题