最初の質問: データはどこから来たのですか? c_str()
ローカル変数の結果を返すことはできません。これは未定義の動作であり、動作しているように見えるのは運が悪いだけです。valueString
より長期的なデータの単なるコピーである場合は、それをc_str
直接呼び出すことができます。ただし、より一般的には、返されるものは何でも、使用する前に有効であることを確認する必要があります。最も簡単な解決策 (ただし、常に可能であるとは限りません) は、 でセンティナル値を使用することですstring
。たとえば、次のようになります。
std::string
getValue( std::string const& key )
{
// ...
return condition ? valueString : std:;string();
}
たとえば、空の文字列をセンティナルとして使用します。
関数のセマンティクスが便利なセンティナル値を提供しない場合 (たとえば、関数が有効な値として空の文字列を返すことができる場合)、別のことを行う必要があります。
戻り値が長寿命のコンテナーでのルックアップの結果である場合、コンテナー内の要素へのポインターを返すことができる場合があります。ただし、一般に、ポインターは何を指すかという問題を引き起こします。寿命が十分にあるものがない場合は、ポインターを使用したくありません。
もう 1 つの可能性は、呼び出し元がデフォルト値を提供することです。
std::string
getValue( std::string const& key, std::string const& ifNotFound )
{
// ...
return condition ? valueString : ifNotFound;
}
これにより、番兵を定義する責任が呼び出し先に移ります。文字列のような場合、ほとんどの場合、呼び出し先が何もできない値が存在するため、センティナルとして使用できます。
最も一般的な代替手段は、ある種のFallible
またはクラスです。ステータス (通常は のみ) と実際のデータ型のインスタンスMaybe
を組み合わせたクラス オブジェクトです。bool
データが有効かどうかはステータスの値に依存するため、次のことを確認する必要があります。
Fallible<std::string>
getValue( std::string const& key )
{
// ...
return condition
? Fallible<std::string>( valueString )
: Fallible<std::string>();
}
これは多くの場合、内部的にもうまく機能します。
Fallible<std::string>
getValue( std::string const& key )
{
Fallible<std::string> results;
// ...
// At some point, I've got a valid return value, so I do:
results.validate( valueString );
// in a condition, of course...
return results;
}
(頻繁で便利なパターンの例にすぎません。)