有一条规则说明std :: tuple的成员被破坏了吗?
例如,如果 Function1
将 std::tuple<std::unique_ptr<ClassA>, std::unique_ptr<ClassB>>
返回到 Function2
,那么我可以确定(当 Function2
的范围被保留时)第二个成员引用的 ClassB
实例在第一个成员引用的 ClassA
实例之前被销毁了吗?
std::tuple< std::unique_ptr< ClassA >, std::unique_ptr< ClassB > > Function1()
{
std::tuple< std::unique_ptr< ClassA >, std::unique_ptr< ClassB > > garbage;
get<0>(garbage).reset( /* ... */ );
get<1>(garbage).reset( /* ... */ );
return garbage;
}
void Function2()
{
auto to_be_destroyed = Function1();
// ... do something else
// to_be_destroyed leaves scope
// Is the instance of ClassB destroyed before the instance of ClassA?
}
3 回答
该标准未指定
std::tuple
的销毁顺序 . §20.4.1/ p1指定的事实是:Similar 此处未被解释为 identical ,因此并不暗示
std::tuple
应具有其参数的反向销毁顺序 .鉴于
std::tuple
的递归性质,最可能的是破坏的顺序与其参数的顺序是一致的 .我的假设基于GCC BUG 66699的错误报告,在讨论中我的假设是合理的 .
That said, the order of destruction for std::tuple is unspecified.
为了回答你的问题,我将提供一个我学到的生活课程,而不是直接的答案:
在元组的上下文中 - 请,请善待维护代码的人,不要让元组元素的破坏顺序可能破坏其他元素的破坏 . 那只是邪恶的......想象一下需要调试这个东西的不幸的程序员 . 事实上,这个可怜的灵魂可能会在几年内成为你自己,当时你已经忘记了当时的巧妙伎俩 .
如果你绝对必须依赖于破坏顺序,也许你应该只使用一个正确的类,将元组的元素作为其数据成员(你可以编写一个析构函数,明确需要以什么顺序发生的事情),或者其他一些安排有助于更明确地控制破坏 .
使用Clang 3.4,我得到了
std::pair
和2个元素std::tuple
的相同销毁顺序,并且使用g 5.3我得到相反的顺序,这可能主要是由于libstd中std::tuple
的递归实现 .所以,它基本上归结为我在评论中所说的,它是实现定义的 .
来自BUG报告:
Martin Sebor的评论
臭虫记者引用的标准[第20.4.1节]的引用
在链接的bug中对此进行的争论是: