shared_ptr、unique_ptr和weak_ptr的最佳用例是什么?



虽然通过了解它们是什么很容易了解std::shared_ptrstd::unique_ptrstd::weak_ptr,但我似乎很难理解它们在什么情况下被证明是有用的。

谁能举出其中三个的具体例子?

我假设你知道这些智能指针中的每一个都做了什么,所以我不打算解释它们。相反,我将给你一些例子,说明我如何在我自己的代码中使用它们,或者从我需要它们的库中使用它们。

std::unique_ptr:可以从 API 返回,以指示资源需要由调用方管理,并且共享对象不安全。例如,gRPC 创建CompletionQueue这样的实例。CompletionQueue具有敏感的生存期和同步要求。通过返回unique_ptr很明显,调用者负责生命周期管理,这使得共享CompletionQueue变得很麻烦。共享它仍然不是不可能(可以从unique_ptr获取原始指针或使用对unique_ptr的引用,这两者都是典型的代码气味)。

std::shared_ptr/std::weak_ptr:不是最简单的用例,但我们开始了...

AudioPlayer::AudioPlayer() {
thread_local std::weak_ptr<AudioPlayerMixer> mixedOutput;
if (mixedOutput.expired()) {
m_mixedOutput = std::make_shared<AudioPlayerMixer>();
mixedOutput = m_mixedOutput;
} else {
m_mixedOutput = mixedOutput.lock();
}
}

在此示例中,线程上的所有AudioPlayer实例都需要使用AudioPlayerMixer将其音频混合在一起。因此,每个AudioPlayer都有一个shared_ptr<AudioPlayerMixer>,因此当保存shared_ptr的最后一个AudioPlayer实例被销毁时,混音器也将销毁。使用thread_local只是有助于每个线程具有唯一的AudioPlayerMixerAudioPlayerMixerthread_local存储不应延长混频器的寿命,因为AudioPlayerMixer的寿命取决于AudioPlayer实例的存在(即没有AudioPlayer=>没有AudioPlayerMixer) - 这就是使用weak_ptr的原因。mixedOutput.expired() == true意味着此线程上未创建任何AudioPlayer,或者删除了所有以前存在的玩家。mixedOutput.expired() == false表示此线程上存在另一个AudioPlayer,当前AudioPlayer需要将shared_ptr到同一混音器。请注意,使用来自多个线程的shared_ptrweak_ptr时必须小心,因为它们不是线程安全的。在此示例中,thread_local以及仅在同一线程中创建和销毁AudioPlayer的事实可确保它是安全的。

当然,这一切都可以在没有智能指针的情况下完成,但智能指针有助于更好地传达代码的意图。

相关内容

  • 没有找到相关文章

最新更新