unique_ptr нормально для владельца. Если необработанные указатели на этот объект все еще выдаются и хранятся в другом месте (и поэтому технически доступны), это может сбить с толку читателей вашего кода.
Если вы не хотите использовать shared_ptr и не хотите иметь висячие указатели, вам может помочь шаблон наблюдателя. Используя его, вы можете убедиться в том, что экземпляр класса B получит сигнал, когда его _z будет уничтожен. Это может быть немного дороже, чем shared_ptr в A и weak_ptr в B. Для примера с безопасным потоком попробуйте ... Boost.Signals2 .
Я согласен, что использование weak_ptr выглядит уродливо, но наблюдатель также добавит немного кода в код.