父对象构造期间不受限制的联合成员生命周期

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 版本。