web-dev-qa-db-ja.com

null shared_ptrを返すことは正しいですか?

たとえば、オブジェクトを検索し、オブジェクトが見つかった場合はshared_ptrを返し、オブジェクトが見つからなかったことを何らかの方法で示す必要がある関数があります。

std::vector<std::shared_ptr> Storage::objects;

std::shared_ptr<Object> Storage::findObject()
{
  if (objects.find)
  {
    return objects[x];
  }
  else
  {
    return nullptr;
  }
}

std::shared_ptr<Object> obj = Storage::findObject();
if (obj)
{
  print("found");
}
else
{
  print("not found");
}
  1. 上の例のように、nullptrで暗黙的に初期化されたshared_ptrを返すことは正しいですか?動作しますが、この方法で実行できますか?または、代わりに構築されたshared_ptrデフォルトを返す必要がありますか?

  2. Weak_ptrになる場合はどうなりますか?空のweak_ptrが返されたことを確認する適切な方法は何ですか? weak_ptr :: expired関数によって、または他の方法はありますか? weak_ptr :: expiredによるチェックが唯一の方法である場合、関数が空のポインターを返したか、オブジェクトが削除されただけか(マルチスレッド環境)をどのように区別できますか?

12
John Lock

上の例のようにnullptrで暗黙的に初期化されたshared_ptrを返すことは正しいですか?

はい、shared_ptrnullptrで初期化することは正しいことです。 nullptrshared_ptrに割り当てることも正しいです。

または、代わりに構築されたshared_ptrデフォルトを返す必要がありますか?

これは両方の方法で行うことができます。

  1. nullptrで初期化されたshared_ptrを返す

    return shared_ptr<Object>(nullptr);
    
  2. 構築されたshared_ptrのデフォルトを返します。

    return nullptr;
    

どちらの方法も正しく、どちらも同じ効果があります。好きなように使うことができます。

Weak_ptrになる場合はどうなりますか?空のweak_ptrが返されたことを確認する適切な方法は何ですか? weak_ptr :: expired関数によって、または他の方法はありますか?

オブジェクトに関連付けられた最後のweak_ptrが破棄されると、shared_ptrnullptr(期限切れ)になります。

weak_ptrを使用する適切な方法は、それを lock メソッドを使用してshared_ptrに変換し、作成されたshared_ptrを使用することです。その場合、weak_ptrは、新しいshared_ptrを取得するまで有効期限が切れません。 weak_ptrshared_ptrに変換しない場合、weak_ptrはいつでも期限切れになる可能性があります。

そして、はい、新しく作成したshared_ptrを使用する前に、lockメソッドでweak_ptrを作成する前にshared_ptrが期限切れになっている可能性があるため、それがnullでないことを確認する必要があります。

std::weak_ptr<Object> Storage::findObject();

...

std::weak_ptr  <Object> weak   = Storage::findObject();
std::shared_ptr<Object> shared = weak.lock();
if (shared) // check that weak was not expired when we did "shared = weak.lock()"
{
    // do something with shared, it will not expire.
}
12
anton_rh