Как использовать lock_guard при возврате защищенных данных

У меня есть вопрос относительно использования boost::lock_guard (или аналогичных блокировок) и использования переменных, которые должны быть защищены блокировкой в ​​инструкции return.

Как порядок уничтожения локальных объектов и копирование возвращаемого значения? Как оптимизация возвращаемого значения влияет на это?

Пример:

Data Class::GetData()
{
    boost::lock_guard<boost::mutex> lock(this->mMutex);
    return this->mData;
}

Правильно ли это (если mData является переменной, защищенной mMutex)? Или мне придется использовать локальную область действия и временную, как показано в примере ниже:

Data Class::GetData()
{
    Data ret;
    {
        boost::lock_guard<boost::mutex> lock(this->mMutex);
        ret = this->mData;
    }
    return ret;
}

Ответы

Ответ 1

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

Ответ 2

Как порядок уничтожения локальных объектов и копирование возвращаемого значения?

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

Как оптимизация возвращаемого значения влияет на это?

RVO не должно вызывать беспокойства здесь - все это - это создание выходного объекта непосредственно в буфер фрейма стека - исключая накладные расходы на создание именованного временного объекта (как в вашем втором примере выше). Это делается до вызова локальных деструкторов.

Лучше всего использовать код из примера 1 выше.

Ответ 3

Обе части эквивалентны. Фактически для случая # 1 - компилятор С++ создаст структуру, описанную в случае №2. Поэтому № 1 предпочтительнее.