C++ C++;std::元组破坏顺序
是否有一条规则规定std::tuple的成员按什么顺序销毁 例如,如果C++ C++;std::元组破坏顺序,c++,c++11,std,stdtuple,C++,C++11,Std,Stdtuple,是否有一条规则规定std::tuple的成员按什么顺序销毁 例如,如果Function1将std::tuple返回到Function2,那么我是否可以确保(当Function2的范围保留时)第二个成员引用的ClassB实例在第一个成员引用的ClassA实例之前被销毁 std::tuple< std::unique_ptr< ClassA >, std::unique_ptr< ClassB > > Function1() { std::tuple<
Function1
将std::tuple
返回到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?
}
std::tuple,std::unique_ptr>Function1()
{
std::tuple,std::unique\u ptr>垃圾;
获取(垃圾)。重置(/*…*/);
获取(垃圾)。重置(/*…*/);
回收垃圾;
}
无效函数2()
{
自动销毁=功能1();
//…做点别的
//被破坏的范围
//ClassB实例是否在ClassA实例之前被销毁?
}
对于Clang 3.4,我对std::pair
和2元素std::tuple
得到了相同的销毁顺序,而对于g++5.3,我得到了相反的顺序,这可能主要是由于在libstd++中递归实现了std::tuple
所以,它基本上可以归结为我在评论中所说的,它是实现定义的
从报告中可以看出:
Martin Sebor的评论
由于std::pair成员的布局是完全指定的,所以
初始化和销毁的顺序。测试的输出
本案反映了这一顺序
std:stuple子对象的初始化(和销毁)顺序
没有那么明确的规定。至少从现在来看还不明显
如果需要任何特殊订单,请阅读规范
使用libstdc++输出std::tuple的原因与此相反
之所以使用std::pair是因为实现依赖于递归
继承,以相反的方式存储和构造元组元素
顺序:即存储最后一个元素的基类
首先构造,然后是每个派生类(每个
存储最后一个元素(第n个元素)
错误报告者引用的标准[第20.4.1节]中的引用
1本小节描述了提供元组的元组库
类型为类模板元组,可以使用任何
参数的数量。每个模板参数都指定模板的类型
元组中的元素。因此,元组是异构的,
固定大小的值集合具有两个参数的元组的实例化
参数类似于具有相同两个参数的pair的实例化
参数。见20.3
链接错误中对此提出的反对意见如下:
被描述为相似并不意味着它们在每个方面都是相同的
细节std::pair和std::tuple是具有不同属性的不同类
对每一项的要求。如果您认为要求员工表现良好
在这方面相同(即,将其子对象定义在
相同的顺序)您需要指出
我保证
对于你的问题,我将提供我学到的人生课程,而不是直接的回答: 如果您可以为多个备选方案制定一个合理的论据,说明为什么该备选方案应为本标准规定的备选方案,那么您不应假设其中任何一个备选方案是强制性的(即使其中一个恰好是强制性的) 在元组上下文中-请,请善待维护代码的人员,不要让元组元素的销毁顺序潜在地破坏其他元素的销毁。那太邪恶了。。。想象一下,一个倒霉的程序员需要调试这个东西。事实上,那可怜的灵魂可能在几年后变成你自己,那时你已经忘记了你那聪明的把戏
如果您绝对必须依赖于销毁顺序,那么您可能应该使用一个适当的类,将元组的元素作为其数据成员(您可以为其编写一个析构函数,明确需要以什么顺序发生什么),或者有助于更明确地控制销毁的其他安排。标准没有规定
std::tuple
的销毁顺序。§20.4.1/p1规定:
具有两个参数的元组的实例化类似于
具有相同两个参数的对的实例化
相似在这里不被解释为相同,因此并不意味着std::tuple
的参数的销毁顺序应该相反
鉴于std::tuple
的递归性质,最可能的情况是破坏顺序与其参数顺序一致
我的假设也基于bug报告,在讨论中,我的上述假设是合理的
也就是说,
std::tuple
的销毁顺序未指定。我猜这主要取决于标准库中如何实现std::tuple
。我在规范中找不到任何指定std::tuple
销毁顺序的内容。可能应该以未指定的形式提交。最近,Antony Polukhin的excellet CPPCon 2016中提到了这个问题,即在没有适当语言支持的情况下,在C++14中实现部分反射。IIRC他说他唯一可怕的事情是重新实现std::tuple来强制执行特定的初始化顺序。还有,ping@101010。你怎么知道std::pair
元素的销毁顺序是相反的?类似!=identical.@deepmax基于libcxx和libstd++for std::pair上的实现。@101010我不知道,我认为雷同类似于雷同。@yakk非常类似于雷同,但不完全相同于雷同:)这是一堂非常重要的课!当程序