C++ 字符串由返回字符的函数赋值* 更新:对于getValue函数,我没有控制权,所以我可以从我这边做些什么吗?
我有一个关于字符串和char*basic的愚蠢问题 我正在使用一个返回char*值的函数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
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:;}