Собственность с физическим представлением
После прочтения RAII, просмотра презентации Херба Саттера на CppCon2014 и прочтения основных руководящих принципов и связанных с ними статей в течение нескольких дней я все еще не совсем понимаю, что такое собственность и связанная с ней семантика.
Допустим, класс A и класс B представляют физические объекты, и есть класс Scene и класс Process. Класс Process является main
функция, если хотите. В реальном мире A может приобрести B и физически сохранить его для себя. Это может также выпустить это. Поэтому в течение экземпляра Process объект A должен иметь возможность иметь для себя экземпляр B, а также освобождать его после того, как он покончит с ним. Как и Б живут в сцене, которой должен управлять процесс.
Также выводится B: A использует некоторый интерфейс, в то время как сцена использует некоторый другой интерфейс, предоставляемый B.
Давайте попробуем с некоторым кодом по крайней мере для процесса:
class Process
{
public:
void run();
};
void Process::run()
{
auto scn = Scene {};
auto a = A {};
auto b = B {};
scn.add(a); // stores a
scn.add(b); // stores b
a.acquire(b); // stores b, and represents physical possession of a B
a.doSomething();
a.release(b); // sets a's B instance to null, and physically loses the B
}
Поправьте меня здесь, если я ошибаюсь, это сомнительная часть.
Из того, что я понимаю, A должен (а не как код) находиться в куче и указывать на shared_ptr, так как у Process и Scene есть свои собственные экземпляры A. То же самое произошло бы для B, который хранится как в a
И в scn
и который находится в процессе. Зачем тогда scn
не быть make_unique
д?
Другой способ сделать это - поместить все в стек (как в фрагменте кода). Оба решения кажутся мне идентичными, я вообще не понимаю семантической разницы этих двух вариантов, но я бы предпочел первый.
1 ответ
Владение C++ по сути сводится к тому, "кто несет ответственность за удаление этого конкретного объекта, если они умрут в этот конкретный момент". В вашем примере, поскольку все объекты имеют автоматическое время жизни, все они принадлежат Process::run
сам. Там нет передачи права собственности, участвующих в любом из add
, acquire
или же release
,
А как насчет того же самого с объектами с динамическим временем жизни? Ваше описание (где я предполагаю, C
ты имеешь в виду Scene
) все еще можно реализовать двумя различными способами:
Scene
держитstd::unique_ptr
сA
х, это данностьScene
а такжеA
может держать либоstd::unique_ptr
с илиstd::shared_ptr
сB
,
Выбор во втором пункте может быть сделан через определение собственности, которое я изложил выше. Что происходит, когда и A
умирает, держа B
?
- Если
B
должен умереть, тогдаA
является его единственным владельцем и должен держать его черезstd::unique_ptr
- Если
B
должен оставаться внутриScene
, затемScene
а такжеA
оба владельцы, и оба должны держатьB
черезstd::shared_ptr
Сюда не входят не владеющие (необработанные) указатели, которые могут быть полезны (например, если A
владеет B
но Scene
все еще нужна прямая ссылка для любой цели). Они должны быть обновлены отдельно.