Можно ли хранить объект критического раздела в std::vector?

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

Означает ли это, что его нельзя безопасно хранить в коллекции стилей std::vector как экземпляр?


person Nicholas    schedule 10.06.2019    source источник
comment
Я предполагаю, что это не класс С++? если бы это было так, то его копирование/перемещение должно быть явно удалено.   -  person Brad Allred    schedule 11.06.2019
comment
звучит похоже на std::mutex (не копируемый и не перемещаемый), а ответ здесь указывает, что да, вы можете< /i>, но вы не можете сделать ничего, что потенциально могло бы изменить размер вектора (это означает, что вы можете построить его только с фиксированным размером)   -  person kmdreko    schedule 11.06.2019
comment
кроме того, unique_ptr может быть вариантом для безопасного хранения ссылок на них внутри std::vector   -  person Brad Allred    schedule 11.06.2019
comment
однако структуры Windows API обычно просто объявляются как POD, что означает, что вы не получите ошибку компилятора, если попытаетесь скопировать или переместить ее:/   -  person kmdreko    schedule 11.06.2019
comment
@BradAllred это часть C API   -  person M.M    schedule 11.06.2019
comment
я сначала спрашиваю - какой смысл вообще хранить его в std::vector ?   -  person RbMm    schedule 11.06.2019


Ответы (1)


Правильный; объект CRITICAL_SECTION не следует копировать/перемещать, так как он может перестать работать (например, возможно, он содержит указатели на себя).

Одним из подходов было бы сохранение вектора интеллектуальных указателей, например. (код С++ 17):

#include <windows.h>
#include <memory>
#include <vector>

using CS_ptr = std::unique_ptr<CRITICAL_SECTION, decltype(&DeleteCriticalSection)>;

CS_ptr make_CriticalSection(void)
{
    CS_ptr p(new CRITICAL_SECTION, DeleteCriticalSection);
    InitializeCriticalSection(p.get());
    return p;
}

int main()
{
    std::vector<CS_ptr> vec;
    vec.push_back( make_CriticalSection() );    
}

Рассмотрите возможность использования std::recursive_mutex, который является заменой CRITICAL SECTION (и, вероятно, просто обертывает его в реализации Windows) и выполняет правильную инициализацию и выпуск в своем деструкторе.

Стандартные мьютексы также нельзя копировать, поэтому в этом случае вы должны использовать std::unique_ptr<std::recursive_mutex>, если вам нужен их вектор.

Как обсуждалось здесь, также подумайте, действительно ли вы хотите std::mutex вместо рекурсивного мьютекс.

ПРИМЕЧАНИЕ. Windows Mutex — это межпроцессный объект; std::mutex и друзья соответствуют CRITICAL_SECTION.


Я бы также предложил пересмотреть необходимость вектора мьютексов; может быть лучшее решение для того, что вы пытаетесь сделать.

person M.M    schedule 11.06.2019