在析构函数中保存 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 互斥锁来确保,例如在工厂中构建或在共享指针中销毁。
我正在尝试确定以下代码是否安全,或者它是否是 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 forX
’s direct non-variant non-static data members, the destructors forX
’s non-virtual direct base classes and, ifX
is the type of the most derived class (15.6.2), its destructor calls the destructors forX
’s virtual base classes. ...
这肯定地回答了你的问题。
析构函数体在任何成员被析构之前执行。从这个意义上说,它是安全的。
但在问它是否安全之前,必须先问一下是否有任何合理的用例在析构函数(以及构造函数)中保存互斥锁。
只有一个线程可以构造或销毁一个对象。这必须由对象的 outside 互斥锁来确保,例如在工厂中构建或在共享指针中销毁。