父对象构造期间不受限制的联合成员生命周期
unrestricted union members lifetime during parent object construction
通常情况下,您对不受限制的工会成员的生命周期负责——通常您通过就地 ctor/dtor 调用来完成。但是,显然,编译器至少在一种情况下可以帮助您——在下面的代码中,如果对象构造失败,它的(以前构造的)联合成员会自动销毁(至少在 MSVC 2015 中),即我们从不泄漏。
#include <string>
struct CanThrow
{
CanThrow() { throw 0; }
};
struct A
{
A() : str{} {} // note that we don't explicitly call str dtor here
~A() { str.~basic_string(); }
union { std::string str; };
CanThrow ct;
};
int main() { try{ A a; } catch(...) {} }
免责声明:此代码在我的 MSVC 2015 上编译
问题 -- 这是标准保证的吗?它在哪里规定的?
恰恰相反:不应该发生!
[C++11: 9.5/8]:
A union-like class is a union or a class that has an anonymous union as a direct member. A union-like class X
has a set of variant members. If X
is a union its variant members are the non-static data members;
otherwise, its variant members are the non-static data members of all anonymous unions that are members of X
.
[C++11: 15.2/2]:
An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object’s destructor will be invoked. If the object was allocated in a new-expression, the matching deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.
如果Visual Studio这样做,则不合规; FWIW,GCC 6.3 seems to be also.
请注意,(当前)C++17 的措辞有所不同,并且确实允许我们观察到的情况; this change appears to have been introduced by CWG issue #1866 in 2014,所以这很可能是主要编译器 "ahead of the game" 并且不太遵守标准的时期之一(尽管有 -std
标志)。
所以答案是,不,标准当然不能保证在 MSVS 2015 的情况下,尽管将来会保证软件的 C++17 版本。
通常情况下,您对不受限制的工会成员的生命周期负责——通常您通过就地 ctor/dtor 调用来完成。但是,显然,编译器至少在一种情况下可以帮助您——在下面的代码中,如果对象构造失败,它的(以前构造的)联合成员会自动销毁(至少在 MSVC 2015 中),即我们从不泄漏。
#include <string>
struct CanThrow
{
CanThrow() { throw 0; }
};
struct A
{
A() : str{} {} // note that we don't explicitly call str dtor here
~A() { str.~basic_string(); }
union { std::string str; };
CanThrow ct;
};
int main() { try{ A a; } catch(...) {} }
免责声明:此代码在我的 MSVC 2015 上编译
问题 -- 这是标准保证的吗?它在哪里规定的?
恰恰相反:不应该发生!
[C++11: 9.5/8]:
A union-like class is a union or a class that has an anonymous union as a direct member. A union-like classX
has a set of variant members. IfX
is a union its variant members are the non-static data members; otherwise, its variant members are the non-static data members of all anonymous unions that are members ofX
.
[C++11: 15.2/2]:
An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object’s destructor will be invoked. If the object was allocated in a new-expression, the matching deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.
如果Visual Studio这样做,则不合规; FWIW,GCC 6.3 seems to be also.
请注意,(当前)C++17 的措辞有所不同,并且确实允许我们观察到的情况; this change appears to have been introduced by CWG issue #1866 in 2014,所以这很可能是主要编译器 "ahead of the game" 并且不太遵守标准的时期之一(尽管有 -std
标志)。
所以答案是,不,标准当然不能保证在 MSVS 2015 的情况下,尽管将来会保证软件的 C++17 版本。