【问题标题】:Need help in understanding meaning of ' string ltrim(const string &) '需要帮助理解'string ltrim(const string &)'的含义
【发布时间】:2019-11-03 14:48:47
【问题描述】:

我几乎没有 C++ 经验。我的问题更多是关于确认我是否通过一些查询正确思考。我试图理解一个代码,它有以下行:

string ltrim(const string &);

我看到了以下答案: 1.What is the difference between "std::string const &s" and "const std::string &s"? 2.https://www.geeksforgeeks.org/stdstring-class-in-c/ 3.https://codereview.stackexchange.com/questions/32842/passing-parameters-by-reference

我知道按值调用和按引用调用的概念。

  1. 什么是“ltrim”?

在我看来,这是一个在这里声明的函数名,因为我知道 C++ 没有使用这个名称的预定义函数。我是否正确假设这意味着它是一个名为“ltrim”的“字符串”类型的函数,并且该函数有一个参数“常量字符串类型”。

但是,通常我们有这样的功能:

void abc (int &a)

其中 a 是一个变量。里面的变量是什么:

string ltrim(const string &);

因为 'const' 具有预定义的含义,而 'string' 是一种数据类型。参数中传入的变量是什么?

  1. 另外,如果没有变量,'&' 在这里做什么。我理解一些 w.r.t C++ 的引用调用,但我没有看到变量名,我不知道 s 用来传递什么。

我尝试在互联网上查找一些信息,但我无法找到一个用字符串解释这一点的地方。

【问题讨论】:

    标签: c++ string c++11 pass-by-reference


    【解决方案1】:

    C++ 中函数原型的目的是告诉编译器

    • 函数的名称是什么,
    • 其参数的类型是什么,以及
    • 它返回什么类型(如果有)。

    这里的一个重要细节是上面的列表包括参数的名称。例如,以下所有代码段都声明了相同的函数:

    int myFunction(int a, double b);
    int myFunction(int apples, double bananas);
    int myFunction(int pizkwat, double zyzzyzyplyz);
    

    此外,myFunction 的实际实现不需要使用此处给出的任何名称。例如,我们可以写

    int myFunction(int snickerdoodle, double alfajores) {
        // ... do something ... //
    }
    

    并且编译器会非常满意,即使上述原型都没有使用这些名称。

    现在,对于一个奇怪的 C++ 琐事:在 C++ 中,可以声明具有没有名称的参数的函数。例如,这段代码是完全合法的:

    void doSomething(int) {
       // This function takes in an integer. You can't call it without
       // passing in that integer. However, this function has no way of
       // referencing its argument, because it doesn't have a name!
    }
    

    您确实在实践中看到了这一点。例如,重载后缀++ 运算符需要声明一个名为operator++ 的函数,该函数接收一个int,其值基本上从未使用过。或者,您可能正在重写派生类中的函数并且不需要使用提供的参数。

    这意味着我们在 C++ 中有三个规则:

    规则一:忽略函数原型中的参数名称。

    规则二:函数实现不必为其参数选择与其原型相同的名称。

    规则三:参数甚至不需要有名称。

    通过将这三个规则组合在一起,您有时会看到这样的情况:

    int myFunction(int, double); // Prototype gives no names to arguments
    
    int myFunction(int a, double b) {
        // .. use parameters a and b ... //
    }
    

    这里,函数原型没有给它的参数命名,但是没关系! C++ 仍然学习有关函数所需的一切(名称、返回类型和参数类型)。由于规则一和规则三,这是合法的。在实际需要引用参数的实现中,这些参数被赋予名称ab。由于规则二,这些参数现在有了名称这一事实很好。

    所以,回到你的例子,函数原型

    string ltrim(const string &);
    

    表示“我正在声明一个名为 ltrim 的函数。它接受对 const string 的引用,并返回 string。”完全相当于说

    string ltrim(const string& toTrim);
    

    string ltrim(const string& oompaLoompa);
    

    ltrim 的实际实现,从外观上看,几乎可以肯定地命名它的参数,以便它可以引用它并修剪字符串。

    希望这会有所帮助!

    【讨论】:

    • 你是一个oompaLoompa
    • 我看到这个很晚,但这是一个很好的解释!谢谢。
    • 在原型中包含变量名称的情况,或者在实现中具有名称但将其注释掉的情况,如果命名良好,是否记录了变量将是(或本来是)用于。有时,标题中的函数原型将是您将获得的有关如何使用该函数的唯一有价值的文档,因此如果它是完整且具有描述性的,那就太好了。
    【解决方案2】:

    什么是'ltrim'?

    您的猜测是正确的,ltrim (left-trim) 是一个接受 const std::string& 作为参数并返回 std::string 的函数。我们实际上不需要为参数命名,因为我们还没有使用该参数。我们只会在定义函数体后使用它,当前代码行只是对函数的声明。

    另外,如果没有变量,'&' 在这里做什么。我明白 通过引用调用一些 w.r.t C++,但我没有看到变量 名字,我不知道用来传递什么。

    仅仅因为没有变量名并不意味着函数不能请求对某个类型的引用。引用类型是类型的一部分,而不是变量名的一部分,参数名是完全可选的:

    void Foo(int, const int&, int*)
    {
      // stuff..
    }
    
    int main()
    {
      Foo(1, 2, nullptr);
    }
    

    只要Foo 不尝试访问参数,这段代码是完全合法的。不能,因为他们没有名字。


    拆分声明和定义并在其中一个中为参数命名而不在另一个中命名也是完全有效的:

    void Foo(int);
    
    int main()
    {
      Foo(1);
    }
    
    void Foo(int bar)
    {
      // stuff with 'bar'...
    }
    

    【讨论】:

    • 这里有一件有趣的事情是,在定义(不是声明)中,没有名称的参数表示未使用的参数。这似乎有点多余,因为它当然是未使用的,因为它不可能,它没有名字!但这是一个需要记住的重要细节,因为它可以用来隐藏关于未使用参数的编译器警告。它告诉编译器该参数未使用,并且您知道它未使用并打算不使用它,因此不应发出警告。
    【解决方案3】:

    该行声明了一个名为 ltrim 的函数,该函数返回一个 string 并接受一个参数:对 const string 的引用。

    参数的名称是可选的。在这种情况下,函数 definition 很可能具有该参数的名称,但也可以在此处省略。如果函数定义中未命名参数,则无法在函数体中引用该参数,但如果您需要接受参数以实现某些接口但实际上不需要使用它,则它会很有用。

    【讨论】:

      【解决方案4】:
      string ltrim(const string &);
      

      这行代码声明存在一个名为ltrim 的函数,它接受一个未命名的const string& 参数,并返回一个string

      令人困惑的部分是 C++ 不需要函数参数的名称!当需要保留接口但实现不再使用参数时,您会看到这种情况。

      【讨论】:

        猜你喜欢
        • 2018-07-05
        • 1970-01-01
        • 2019-10-07
        • 1970-01-01
        • 2016-04-12
        • 2013-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多