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>在*/Cuth>之前。

< P>这不是C,它是C++,通过引用使您的生活更容易:

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]
,因为运算符优先

有三种方法可以避免这种情况:

  • 更改界面:
  • <>在C++中允许通过引用传递对象:

    在函数内部对
    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!)
    }