9

find必要なものが見つからないことがある関数がある場合、その関数がポインタを返すようにして、 a が見つからなかったことを示すようにする傾向がありますnullptr

例えば

Student* SomeClass::findStudent(/** some criteria. */)

Student が存在する場合は、見つかったStudentオブジェクトへのポインターを返します。それ以外の場合は、を返しnullptrます。

boost::optionalもこの目的のために支持されているのを見てきました。たとえば、「何も返さない」関数を実装したい場合、boost::optional をいつ使用し、いつ std::unique_ptr を使用しますか?

私の質問は、この場合、ポインターを返さないのが最善の解決策ではないということです。すなわち、照会された項目が見つからない可能性があります。その場合、nullptr を返すことは完璧な解決策です。boost::optionalのようなもの(または他の同様のソリューション)を使用する利点は何ですか?

findStudent私の例では、 が所有するオブジェクトへのポインタのみを返すことに注意してくださいSomeClass

4

4 に答える 4

11

ここでの戻り値の型の利点は、optional<Student&>使い慣れたすべてのユーザーにとって使用法のセマンティクスがすぐにわかることですoptional(そして、慣れるとすぐに明らかになります)。これらのセマンティクスは次のとおりです。

  • 呼び出し元は を所有しておらずStudent、メモリ管理の責任も負いません。呼び出し元は、既存のオブジェクトへの参照を取得するだけです。
  • この関数が失敗する可能性があることは明らかです。値が得られるかもしれませんが、何も得られないかもしれません。呼び出し元が何らかの方法で結果を確認する必要があることは明らかです。

optional<T>そうではない方法で自己文書化してT*います。さらに、割り当てを必要とせずにあらゆる種類のオブジェクト型を返したい場合に機能するという利点もあります。intまたはdoubleまたはを返す必要がある場合はどうしますかSomePOD?

于 2016-02-09T16:18:28.723 に答える
6

optional<T&>は、その使用が疑わしいため、C++ 標準化トラックから削除されました。これは、非所有とほぼ同じように動作しますが、セマンティクスT*がわずかに異なります (および と紛らわしいほど異なりoptional<T>ます)。T*

optional<T&>基本的に非所有T*であり、かなり奇妙に包まれています。


今、optional<T>別の獣です。

optional<Iterator>コンテナベースの検索アルゴリズムで使用しました。を返す代わりにend()、空のオプションを返します。これにより、ユーザーはアイテムの検索に失敗したかどうかを比較せずに判断でき、次のようなコードを作成できます。

if(linear_search_for( vec, item))

動作しますが、実際に必要な場合は、同じアルゴリズムを使用して、コンテナー内のアイテムアイテムの場所の両方を取得することもできます。

要素へのポインターは、連続したコンテナーを除いて、必要な位置情報を提供しません。

そのため、ここでは、イテレーター (一般的にさまざまな種類のコンテナーで動作する) とポインター (null 状態をテストできる) の利点を持つ null 許容イテレーターを作成しました。

次の使用は、実際に値を返すことです。長方形を計算する関数があるとします。

Rect GetRect();

今、これは素晴らしいです。しかし、質問が無意味である可能性がある場合はどうなりますか? 1 つのアプローチは、空の rect またはその他の「フラグ」値を返すことです。

Optional を使用すると、Rect を返すか何も返さないかを伝えることができ、"nothing" 状態に空の rect を使用しないことができます。戻り値を null 許容にします。

int GetValue();

はより良い例です。無効な値は int のフラグ状態を使用できますが、たとえば-1、関数のすべてのユーザーがフラグ状態を調べて追跡し、誤って通常の状態として扱わないようにします。

代わりに、失敗する可能性があること、および失敗の状態が何であるかoptional<int> GetValue()を明確にします。値が設定されている場合は、フラグ値ではなく、実際の値であることがわかります。

どちらの場合でも、非所有ポインターを返すことは実行できません。なぜなら、誰がストレージを所有しているのでしょうか? 無意味なヒープ割り当ては無意味であるため、所有ポインタを返すことはコストがかかります。

オプションは、null 許容値の型です。リソースをローカルで管理したいが、それでも空の状態が必要な場合は、それが明確になります。


検討すべきもう 1 つのことは、expected提案されているタイプです。これはオプションですが、空の状態の場合、空である理由が含まれています。

于 2016-02-09T16:39:00.187 に答える
3

optional<T&>実際に置き換えられる可能性がありますがT*T*意味が明確ではありません (所有権 ?)。

しかし、optional<T>に置き換えることはできませんT*。例えば:

optional<Interval> ComputeOverlap(const Interval&, const Interval&);

重なりがなければT*nullptr)やで問題ありませんoptional<T>。ただし、オーバーラップがある場合は、新しい間隔を作成する必要があります。この場合、smart_pointer を返すか、オプションです。

于 2016-02-09T16:34:34.537 に答える
2

std::map<IndexType, ValueType>何かを見つけようとしている場所があるとします (注: 他のコンテナにも同じことが当てはまります。これは単なる例です)。次のオプションがあります。

  • を返しますValueType&: ユーザーはマップ コンテンツを変更でき、メモリの割り当て/割り当て解除について考える必要はありません。ただし、マップに何も見つからない場合は、例外または同様のものをスローする必要があります。
  • を返すValueType*: ユーザーはマップ コンテンツを変更でき、何も見つからない場合は nullptr を返すことができます。ただし、ユーザーはそのポインターで delete を呼び出すことができ、そうする必要があるかどうかをとにかく指定する必要があります。
  • You return a smart pointer to ValueType: ユーザーは削除または非削除について心配する必要がなく、スマート ポインターの種類に応じてマップ コンテンツを変更できます。nullptr を返すこともできます。しかし、これにはマップ内の smart_pointers を処理する必要があり、ValueTypeそれ以外の場合は単に int の場合は非常に複雑です。
  • シンプルな を返しますValueType: ユーザーはマップ コンテンツを変更できず、メモリの割り当て/割り当て解除について考える必要はありません。ただし、マップに何もValueType見つからない場合は、何も見つからなかったことをユーザーに知らせる特別なものを返す必要があります。あなたValueTypeが例えばintの場合、「intが見つかりません」を明確にするものを返します。
  • ValueTypeブースト::オプションを返します。これは、 「を返さない」という追加オプションを使用して、値による単純な戻り値にValueType最も近いものです。
于 2016-02-09T16:20:25.293 に答える