C++ C++;Can';t在函数中编辑字符串
我被难住了。我真的搞不懂这个C++ C++;Can';t在函数中编辑字符串,c++,string,function,C++,String,Function,我被难住了。我真的搞不懂这个 int main(){ string blah = "text"; example(&blah); } void example(string *h){ *h[3]='l'; } 在上面的函数中,我尝试在不使用全局变量的情况下编辑原始字符串的第四个字符。我本以为这会奏效,因为我知道我可以用ints做类似的事情。我猜这与字符串/字符转换有关,但我在网上找不到太多信息 这是因为运算符优先级, []/Cord>在*/Cuth>之前。 <
int main(){
string blah = "text";
example(&blah);
}
void example(string *h){
*h[3]='l';
}
在上面的函数中,我尝试在不使用全局变量的情况下编辑原始字符串的第四个字符。我本以为这会奏效,因为我知道我可以用ints做类似的事情。我猜这与字符串/字符转换有关,但我在网上找不到太多信息代码>
这是因为运算符优先级,<代码> []/Cord>在
void example(string & h){
h[3]='l';
}
在C ++中(在那个特定用例中)作为指针传递它是零意义的,即“C++风格”的引用,C++中引用的引用使它过时了。
通常,如果你想使用指针算术,你会想通过指针,一些东西通常被C++标准库容器所淘汰,或者为了符合某些已建立的库API——有大量使用指针,但与你的用例有稍微不同的意图。 顺便说一句,
std::string
有一个at()
方法,与指针一起使用可能会更优雅一些:
h->at(3) = 'l';
当然,您也可以从指针调用[]
操作符作为函数:
h->operator [](3) = 'l';
但这有点违背了目的。问题很简单:
*h[3]
相当于*(h[3])
,而不是(*h)[3]
,因为运算符优先
有三种方法可以避免这种情况:
h
所做的所有更改示例
在“函数外部”可见
void example(std::string* h_ptr)
{
assert( h_ptr != nullptr ); // make sure you didn't pass a NULL pointer
std::string& h = *h_ptr; // create a reference from a non-NULL pointer
h[3] = '1';
}
void example(std::string* h)
{
(*h)[3] = '1'; // be explicit on the order you want (you will often make mistakes!)
}
运算符优先级:
(*h)[3]
。但是,如果您想让它变得简单,请通过引用传递:void-example(string&h){h[3]='1';}
std::string*
eeewww…通过指针而不是引用传递有一个参数:接口的清晰度。如果对象作为常量引用或非常量引用传递,则在调用站点上不可见。通过指针传递对象所需的额外&
,可以在调用站点上看到潜在的更改(例如,google样式指南强制执行此操作)@stefan-没错,但在大多数当代IDE中,您只需将鼠标悬停在调用上即可查看函数签名。通常在为调用键入左括号时也会得到它。只使用assert(h_ptr)
有什么不对?可读性?@ddriver没有错,但这是个人喜好。我认为<代码>断言(HY-PTR.= NulLPTR)非常可读。“非常多”——听起来很充足;另一方面,我发现它不太理想,不仅打字时间更长,而且还增加了另一个层次的推理,不知何故,问“这是不是真的”比问“这不是真的”听起来更清晰:)@ddriver我更喜欢“这指针不是空指针”的说法,而不是“这指针是真的”。指针不是“true”,它是有效的或无效的。事实上,如果使用if
,它将解析为布尔值,该布尔值为true或false。此外,指针可以通过此类检查,如果指向错误的地址,则仍然无效。我同意有时隐式转换是坏的,它们在C++中是太常见的,在很多情况下,代码变得不可读,但在那个特定的场景中,至少不是这样,至少它是这样工作的。不过,“水是湿的是真的吗”听起来比“水不是湿的不是真的吗”要好一点。甜美而简单。传奇
void example(std::string* h)
{
(*h)[3] = '1'; // be explicit on the order you want (you will often make mistakes!)
}