Другое поведение, когда у объекта `std:: lock_guard<std:: mutex>` нет имени

Я учусь о std::mutex, std::thread и я удивлен разным поведением двух частей кода ниже:

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

std::mutex mtx;

void foo(int k)
{
    std::lock_guard<std::mutex> lg{ mtx };
    for (int i = 0; i < 10; ++i)
        cout << "This is a test!" << i << endl;
    cout << "The test " << k << " has been finished." << endl;
}

int main()
{
    std::thread t1(foo, 1);
    std::thread t2(foo, 2);
    t1.join();
    t2.join();
    return 0;
}

Выход является последовательным. Но если я не буду называть имя переменной std::lock_guard<std::mutex>, выход неупорядочен

void foo(int k)
{
    std::lock_guard<std::mutex> { mtx }; // just erase the name of variable
    for (int i = 0; i < 10; ++i)
        cout << "This is a test!" << i << endl;
    cout << "The test " << k << " has been finished." << endl;
}

Это похоже на std::lock_guard бесполезно во втором случае, почему?

1 ответ

Решение

Эта декларация

std::lock_guard<std::mutex> { mtx };

не привязывает созданный объект к имени, это временная переменная, которая существует только для этого конкретного оператора. В противоположность этому переменная, которая имеет имя и создается в стеке, живет до конца области, в которой она создана.

В этом выступлении на CppCon (начиная с 31:42) докладчик перечисляет создание временных std::lock_guard экземпляры, не связанные с локальной переменной, как распространенная ошибка в базе кода Facebook.

Другие вопросы по тегам