Умный указатель с выделением при первом доступе - PullRequest
0 голосов
/ 26 февраля 2020

TL; DR: существует ли реализация класса интеллектуальных указателей, аналогичного std::unique_ptr, который создает экземпляр инкапсулированного объекта только в том случае, когда указатель впервые разыменовывается?

Фон:

У нас есть класс Process, представляющий запущенный процесс. Когда процесс выполняет сетевое взаимодействие, мы записываем это действие и сохраняем его в объекте класса NetworkActivity, который является членом класса Process.

NetworkActivity - это большой класс со многими переменными-членами. Я пытаюсь уменьшить использование памяти и создавать экземпляры NetworkActivity объектов только для небольшого подмножества процессов, которые фактически обмениваются данными по сети.

Я мог бы, конечно, использовать unique_ptr в Process класс:

std::unique_ptr<NetworkActivity> networkActivityPtr;

Но тогда мне нужно будет проверять networkActivityPtr на nullptr каждый раз, когда я разыменую его. Если я забуду такую ​​проверку и память еще не будет выделена, программа вылетит.

Нет ли варианта unique_ptr, который создает объект при первом разыменовании умного указателя?

Ответы [ 2 ]

0 голосов
/ 26 февраля 2020

В целях безопасности потоков вам действительно нужно что-то вроде future<NetworkActivity>. Это проясняет различие между действием доступа к значению указателя (которое является легким и тривиальным, чтобы сделать потокобезопасным) и , создающим объект (который является тяжелым и требует синхронизации потоков, чтобы сделать потокобезопасным). Никто не ожидает, что future::get будет быстрым (может быть, если значение уже доступно, но это не ожидание), в то время как все должны ожидать, что unique_ptr::get будет быстрым.

Тип, который объединяет эти две вещи имеют неопределенные характеристики производительности. get - это то, что вы хотите делать в критичном для производительности коде? Может быть, может и нет; это зависит от того, разумно ли предположить, что значение уже было получено в тот момент выполнения вашего кода.

Вы можете использовать std::async с std::launch::deferred, чтобы использовать future для того, что вы хотите делать. std::launch::deferred гарантирует, что «асинхронный» процесс будет выполняться в том же потоке, что и вызывающий future::get.

0 голосов
/ 26 февраля 2020

Ответ - нет. Смотрите это: Доктор. Статья Доббса . Вам нужно написать свою собственную оболочку.

Однако, когда ваш процесс запускается впервые, его код инициализации создает экземпляр.

...