在析构函数中保存 std::lock_guard 是否安全?

Is it safe to hold a std::lock_guard in the destructor?

我正在尝试确定以下代码是否安全,或者它是否是 UB 并且恰好在这种情况下运行良好(运行 它 here):

#include <iostream>
#include <mutex>

struct Foo
{
  std::mutex mutex;
  ~Foo()
  {
    std::lock_guard<std::mutex> lock(mutex);
  }
};

int main() 
{
  {
    Foo foo;
  }
  std::cout << "everything seems to work fine...?" << std::endl;
}

具体来说,我们能否保证在析构函数中定义的局部变量在成员变量之前被析构?

我从 cppreference.com 中找到了以下内容,但它似乎没有完全回答我的问题:

Destruction sequence

For both user-defined or implicitly-defined destructors, after the body of the destructor is executed, the compiler calls the destructors for all non-static non-variant members of the class, in reverse order of declaration, then it calls the destructors of all direct non-virtual base classes in reverse order of construction (which in turn call the destructors of their members and their base classes, etc), and then, if this object is of most-derived class, it calls the destructors of all virtual bases.

根据[class.dtor]/9中的标准,

After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors for X’s non-virtual direct base classes and, if X is the type of the most derived class (15.6.2), its destructor calls the destructors for X’s virtual base classes. ...

这肯定地回答了你的问题。

析构函数体在任何成员被析构之前执行。从这个意义上说,它是安全的。

但在问它是否安全之前,必须先问一下是否有任何合理的用例在析构函数(以及构造函数)中保存互斥锁。

只有一个线程可以构造或销毁一个对象。这必须由对象的 outside 互斥锁来确保,例如在工厂中构建或在共享指针中销毁。