提问人:Sulphur 提问时间:6/21/2019 更新时间:6/21/2019 访问量:3595
需要帮助理解 ' string ltrim(const string &) ' 的含义
Need help in understanding meaning of ' string ltrim(const string &) '
问:
我几乎没有C++经验。我的问题更多的是确认我是否正确地思考了一些问题。我试图理解一个代码,它有以下行:
string ltrim(const string &);
我看到了以下答案: 1. “std::string const &s” 和 “const std::string &s” 有什么区别?2. https://www.geeksforgeeks.org/stdstring-class-in-c/ 3.https://codereview.stackexchange.com/questions/32842/passing-parameters-by-reference
我知道按值调用和按引用调用的概念。
- 什么是“ltrim”?
在我看来,这是一个在这里声明的函数名称,因为我知道 C++ 没有具有此名称的预定义函数。我是否正确地假设这意味着它是一个名为“ltrim”的函数,类型为“string”,并且该函数具有参数“常量字符串类型”。
但是,通常我们有以下功能:
void abc (int &a)
其中 a 是变量。变量是什么:
string ltrim(const string &);
因为“const”具有预定义的含义,而“string”是一种数据类型。参数中传递的变量是什么?
- 另外,如果没有变量,这里的“&”有什么作用。我理解通过引用调用一些 w.r.t C++,但我没有看到变量名称,我不知道用于传递什么。
我试着在互联网上寻找一些信息,但我无法找到一个用字符串来解释这一点的地方。
答:
string ltrim(const string &);
这行代码声明一个名为的函数存在,它接受一个未命名的参数,并返回一个 .ltrim
const string&
string
令人困惑的部分是 C++ 不需要函数参数的名称!当需要保留接口但实现不再使用该参数时,您将看到这一点。
什么是“ltrim”?
你的猜测是对的,(left-trim) 是一个接受 a 作为参数并返回 .我们实际上不需要像您习惯看到的那样给参数起一个名称,因为我们还没有使用该参数。我们只会在定义函数体后使用它,当前的代码行只是对函数的声明。ltrim
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'...
}
评论
该行声明一个名为的函数,该函数返回 a 并接受单个参数:对 .ltrim
string
const string
参数的名称是可选的。在这种情况下,函数定义可能具有该参数的名称,但也可以省略该名称。如果某个参数在函数定义中未命名,则无法在函数体中引用该参数,但如果您需要接受某个参数来满足某些接口但实际上不需要使用它,它会很有用。
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++ 仍然学习有关函数所需的一切(名称、返回类型和参数类型)。由于规则一和规则三,这是合法的。在实际需要引用参数的实现中,这些参数被赋予了名称和 。由于规则二,这些参数现在具有名称这一事实很好。a
b
所以,回到你的例子,函数原型
string ltrim(const string &);
意思是“我正在声明一个名为 .它接受对 的引用,并返回 。这完全等同于说ltrim
const string
string
string ltrim(const string& toTrim);
或
string ltrim(const string& oompaLoompa);
从外观上看,的实际实现几乎可以肯定地命名了它的参数,以便它可以引用它并修剪字符串。ltrim
希望这有帮助!
评论