3

更新:对于 getValue 函数,我无法控制,所以我能做些什么吗?

我有一个关于 string 和 char * basic 的愚蠢问题。

我正在使用一个返回 char * 值的函数,

const char *getValue(const char *key)
{
    //if key found, and valueString is a string
      return valueString.c_str();
    //else
      return NULL;
}

然后我初始化了一个字符串来保存返回值,

std::string value = getValue(key);

问题是,每当找不到值时,这意味着函数返回 NULL,我的赋值行就会遇到异常。但是当有一个合法的返回值时,一切正常。

我想知道 1. 这种用法完全错误吗?意味着我不应该将 char * 与字符串混合?2.如果不是,那么当返回一个合法的指针时,我的字符串会自动复制并存储吗?3. 最好的方法是什么?

谢谢。

4

6 回答 6

5

首先,如果valueString是该函数的本地函数,使用返回的指针将给出未定义的行为。

其次,返回空指针是否合理将取决于您如何使用该指针,而您什么也没告诉我们。

除非您绝对肯定必须摆弄指针,否则只需返回一个字符串,让您的生活变得更轻松。

于 2012-04-11T18:40:22.853 回答
4

通过返回 NULL来报告错误发生(如果找到键)不是一个好主意。在这种情况下,您应该在函数内部生成有意义的异常。类似的东西NotFoundEx

如果您无法控制该功能,则应将其包装到安全代码中:

const char* getSafeValue(const char *key)
{
  const char* value = getValue(key);
  if(value == NULL)
    throw NotFoundEx();

  return value;
}


std::string value = getSafeValue(key);
于 2012-04-11T20:36:05.863 回答
3

由于您无法控制getValue()函数的作用,因此您需要在将其分配给 NULL 之前检查其返回值std::string

std::string value;  // value is an empty string
const char *retVal = NULL;

if( ( retVal = getValue(key) ) != NULL ) {
  value.assign( retVal );
}
于 2012-04-11T18:49:23.757 回答
0

由于std::string无论如何您都在使用值,因此我将只返回 astd::string而不是 a char*

std::string getValue(const char *key) 
{ 
    if (key found)
        return valueString; 
    else 
        return std::string(); 
} 
于 2012-04-11T18:43:29.413 回答
0

你想要一个std::string超出界限的值。 (char *)可能不是理想的方法(请参阅boost::optional更好的方法),但它会起作用(假设您没有使用堆栈局部变量) -如果您检查超出界限的值。也就是说,这里的问题并不是真正的混合(char *)std::string而是您没有检查“未找到”,而是盲目地假设在这种情况下会发生一些明智的事情。

不要假设;确定如果找不到密钥,您需要做什么,并检查NULL(或其他带外,如果您选择使用其他东西)。

于 2012-04-11T18:43:42.407 回答
0

第一个问题:数据从哪里来?您不能返回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;
}

这将定义哨兵的责任转移给了被调用者。在像字符串这样的情况下,几乎总是有一些被调用者不能做任何事情的值,因此可以用作哨兵。

最通用的选择是某种FallibleMaybe 类:一个结合了状态(通常只是 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;
}

(只是一个常见且方便的模式的例子。)

于 2012-04-11T18:59:29.903 回答