Безопасно ли держать std :: lock_guard в деструкторе? - PullRequest
5 голосов
/ 02 мая 2019

Я пытаюсь решить, является ли следующий код безопасным, или это UB, и он работает только в этом случае (запустите его здесь ):

#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 , но, похоже, он не полностью отвечает на мой вопрос:

Последовательность уничтожения

Как для пользовательских, так и для неявно определенных деструкторов, после выполнения тела деструктора компилятор вызывает деструкторы для всех нестатических не вариантных членов класса в обратном порядке объявления, затем он вызывает деструкторы всех прямых невиртуальных базовых классов в обратном порядке построения (которые в свою очередь вызывают деструкторы их членов и их базовые классы и т. д.), а затем, если этот объект принадлежит к самому производному классу, он вызывает деструкторы всех виртуальных баз.

Ответы [ 2 ]

8 голосов
/ 02 мая 2019

Согласно стандарту в [class.dtor] / 9,

После выполнения тела деструктора и уничтожения любых автоматических объектов, размещенных в теле, деструктор для класса X вызывает деструкторы для прямых не неизменных нестатических элементов данных X, деструкторов для не виртуальных прямых базовых классов X и, если X является типом самого производного класса (15.6.2), его деструктор вызывает деструкторы для виртуальных базовых классов X. ...

Это ответит на ваш вопрос утвердительно.

1 голос
/ 02 мая 2019

Тело деструктора выполняется до того, как любой участник будет уничтожен. В этом смысле это безопасно.

Но перед вопросом, насколько это безопасно, должен быть задан вопрос, есть ли разумный вариант использования для удержания мьютекса в деструкторе (а также в конструкторе).

Только один поток может создать или разрушить объект. Это должно быть обеспечено мьютексом вне объекта, например, при строительстве на заводе или при уничтожении в общей указке.

...