C++ 字符串由返回字符的函数赋值* 更新:对于getValue函数,我没有控制权,所以我可以从我这边做些什么吗?

C++ 字符串由返回字符的函数赋值* 更新:对于getValue函数,我没有控制权,所以我可以从我这边做些什么吗?,c++,C++,我有一个关于字符串和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(ke

我有一个关于字符串和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*和string混在一起? 2.如果没有,那么当返回合法指针时,我的字符串是否会自动复制并存储它? 3.最好的方法是什么


谢谢。

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

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


除非你绝对地、肯定地必须摆弄指针,否则只需返回一个字符串就可以让你的生活更轻松。

既然你使用的是
std::string
值,我只会返回一个
std::string
而不是
char*

std::string getValue(const char *key) 
{ 
    if (key found)
        return valueString; 
    else 
        return std::string(); 
} 

您需要一个带有越界值的
std::string
(char*)
可能不是执行此操作的理想方法(有关更好的方法,请参见
boost::optional
),但如果您检查越界值,它将起作用(假设您没有使用堆栈局部变量)。也就是说,这里的问题并不是将
(char*)
std::string
混合在一起,而是您没有检查“未找到”,而是盲目地假设在这种情况下会发生一些合理的事情


不要假设;确定找不到密钥时需要执行的操作,并检查
NULL
(或其他带外,如果您选择使用其他内容)。

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

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

if( ( retVal = getValue(key) ) != NULL ) {
  value.assign( retVal );
}

第一个问题:数据来自哪里?你不能把钱还回去 局部变量的
c_str()
结果;这是未定义的行为,并且 你只是运气不好,它似乎起作用了。如果
valueString
为 只要复制一些更持久的数据,就可以调用
c\u str
直接在上面。然而,更一般地说:无论你返回什么,你都会 在尝试使用它之前,必须验证它是否有效。最简单的 解决方案(但并非总是可能的)只是在
字符串
,例如:

std::string
getValue( std::string const& key )
{
    //  ...
    return condition ? valueString : std:;string();
}
例如,使用空字符串作为sentinal

如果函数的语义不提供方便的sentinal 值,例如,如果函数可以返回空字符串作为 如果值有效,则必须执行其他操作

如果返回值是某个长字符串中的查找结果 活动容器,则可以返回指向该元素的指针 在容器里。但是,一般来说,指针会带来以下问题: 他们指的是什么;如果你没有什么东西的生命 足够了,那么您就不想使用指针了

另一种可能是调用方提供默认值:

std::string
getValue( std::string const& key, std::string const& ifNotFound )
{
    // ...
    return condition ? valueString : ifNotFound;
}
这就把定义哨兵的责任转移到了士兵身上 卡利。在类似字符串的情况下,几乎总是有一些值 被叫人不能做任何事,所以可以用作哨兵

最普遍的选择是某种
容易出错的
可能
类:组合状态的类对象(通常只是一个
bool
) 和实际数据类型的实例。数据是否有效 not取决于状态的值,因此您仍然需要检查:

Fallible<std::string>
getValue( std::string const& key )
{
    //  ...
    return condition
        ? Fallible<std::string>( valueString )
        : Fallible<std::string>();
}
易出错
getValue(标准::字符串常量和键)
{
//  ...
返回条件
?易出错(valueString)
:易出错();
}
这通常在内部也很有效:

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;
}
易出错
getValue(标准::字符串常量和键)
{
容易出错的结果;
//  ...
//在某些情况下,我得到了一个有效的返回值,因此我:
结果。验证(valueString);
//当然,在某种情况下。。。
返回结果;
}

(这只是一个频繁且方便的模式的示例。)

通过返回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);

最好的方法取决于
getValue
应该做什么。您可以返回
,而不是
NULL
,或者引发异常。我将返回
字符串,而不是
字符*
。感谢您的回复,很抱歉,我没有提到我无法控制我正在使用的函数,我所能做的就是正确使用。顺便说一句,返回变量不是本地变量。在这种情况下,理想情况下,
boost::optional
。为了不让新变量污染代码,您可以在
if
if(const char*retVal=getValue(key)){value.assign(retVal)中声明
retVal
解决方案并不完美……但问题不在用户代码中,而是在库提供的界面中。+1(另一种选择是包装函数:
std::string getValueStr(key_type const&k){const char*r=getValue(k);返回r?r:;}