第一个问题:数据从哪里来?您不能返回c_str()
局部变量的结果;这是未定义的行为,而您似乎很不幸,它似乎起作用了。如果valueString
只是一些更持久数据的副本,那么您可以c_str
直接调用它。然而,更一般地说:无论您返回什么,您都必须在尝试使用它之前验证它是否有效。最简单的解决方案(但并非总是可能)就是在 中使用一个标记值string
,例如:
std::string
getValue( std::string const& key )
{
// ...
return condition ? valueString : std:;string();
}
例如,使用空字符串作为哨兵。
如果函数的语义没有提供方便的标记值——例如,如果函数可以返回一个空字符串作为有效值——那么你将不得不做其他事情。
如果返回值是在某个长期存在的容器中查找的结果,那么您可以返回指向容器中元素的指针。然而,一般来说,指针提出了它们指向什么的问题。如果您没有生命周期足够的东西,那么您不想使用指针。
另一种可能性是调用者提供默认值:
std::string
getValue( std::string const& key, std::string const& ifNotFound )
{
// ...
return condition ? valueString : ifNotFound;
}
这将定义哨兵的责任转移给了被调用者。在像字符串这样的情况下,几乎总是有一些被调用者不能做任何事情的值,因此可以用作哨兵。
最通用的选择是某种Fallible
或Maybe
类:一个结合了状态(通常只是 a 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;
}
(只是一个常见且方便的模式的例子。)