C++ std :: tuple的销毁顺序
是否有规则说明std :: tuple的成员以何种顺序销毁?C++ 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?
}
该标准没有规定销毁的顺序std::tuple
。该§20.4.1/ P1的事实规定:
两个参数元组的一个实例是类似于用相同的两种参数的 实例对。
类似这里不被解释为相同,因此它不意味着std::tuple
应该有它的参数反破坏秩序。
鉴于std::tuple
的递归性质,最可能的是破坏顺序与其参数的顺序一致。
我也基于我对GCC BUG 66699的错误报告的假设,在讨论中我的上述假设是合理的。
也就是说,std::tuple
的销毁顺序是未指定的。
随着锵3.4我得到两个std::pair
和2元件std::tuple
并用克++ 5.3我得到相反的顺序这可能主要是由于在libstd递归执行std::tuple
++相同的破坏顺序。
所以,它基本上归结为我在评论中所说的,它是实现定义的。
从BUG报告:
评论马丁Sebor
由于性病::对成员的布局完全指定,所以是 为了自己的初始化和销毁的。测试 案例的输出反映了这个顺序。
std:stuple子对象 的初始化(和破坏)的顺序不太清楚。至少从 我不清楚如果任何特定的顺序是必需的规范。
之所以输出的std ::元组的libstdC++是反向的std :: 对是因为实现,其依赖于递归 继承,存储和构造元组以相反的顺序 元素:即存储最后一个元素的基类被存储为 ,并且首先构造,然后是每个派生类(其中每个 存储最后的第N个元素)。
从标准[20.4.1节],其错误记者引用到
1本节的报价描述了元组库,提供了一个元组类型 作为类模板的元组,可以是用任何 参数实例化。每个模板参数指定元组中的 元素的类型。因此,元组是异构的,固定大小的值集合。 具有两个参数 的元组实例化与参数相同的两个参数 的实例类似。见20.3。针对这在链接错误作出
的说法是:
描述为类似并不意味着它们在每 细节是相同的。 std :: pair和std :: tuple是不同的类,每个类都有不同的 要求。如果您认为在这方面要求相同地表现 (即,让其子对象在 中定义相同的顺序),则需要指向 保证它的具体措词。
我会提供了一个生命的教训我已经学会了,而不是直接回答,在回答您的问题:
如果你可以制定,对多个备选方案,为什么一个合理的说法该替代方案应该是标准强制要求的替代方案 - 那么您不应该假设其中任何都是(即使其中一个碰巧是)。
在元组的上下文中,请善待维护你的代码的人,不要让元组的销毁顺序潜在地破坏其他元素的销毁。这只是一种邪恶......想象一下这个倒霉的程序员需要调试这个东西。事实上,那些可怜的灵魂可能会在几年后成为你自己,当你已经忘掉了你今天聪明的把戏。
如果你绝对必须依赖销毁顺序,也许你应该使用一个适当的类来处理元组的元素作为它的数据成员(你可以写一个析构函数,明确以什么顺序发生的事情)或其他一些有助于更明确地控制销毁的安排。
这是一个非常重要的课程!在使用C++进行编程时,这个技巧一直在开发人员的头脑中。 – hbobenicio
我不太理解这一点。由于C++ 11字符串需要连续存储。但是有一个合理的论点(在编写C++ 03时使用的论点)不要求这样做。或者,如果你对这个例子提出异议,就选择另一个标准作出判断的电话,这样可以合理地进行。那么我不应该编写依赖于C++ 11或C++ 14收紧的代码吗?或者你的意思是说,如果标准不清楚,那么不要依靠下一位程序员以同样的方式吐毛? –
或者对于一个故意愚蠢的例子,有一个合理的论点:std :: vector应该被称为std :: dynamic_array,而std :: valarray应该被称为std :: vector。但是我认为在std :: vector这个标准的基础上编写代码是非常合理的:我们不能在不假设的情况下使用它。所以我不认为我已经理解了你的建议适用于什么情况;-) –
我猜测它主要取决于如何在标准库中实现'std :: tuple'。 – Arunmu
我找不到指定'std :: tuple'销毁顺序的规范。可能应该提交为未指定。 – 101010
http://stackoverflow.com/a/27663655/576911 –