函数
C++ 中的函数将一系列的 语句 (函数体)与一个名称和零个或多个函数参数相关联。
// function name: "isodd" // parameter list has one parameter, with name "n" and type int // the return type is bool bool isodd(int n) { // the body of the function begins return n % 2; } // the body of the function ends
当函数被调用时,例如在 函数调用表达式 中,参数将从参数(在调用时提供或 默认)中初始化,函数体中的语句将被执行。如果 参数列表 以 ... 结尾,则可以向函数提供额外的参数,这种函数称为 可变参数函数。
int main() { for (int arg : {-3, -2, -1, 0, 1, 2, 3}) std::cout << isodd(arg) << ' '; // isodd called 7 times, each // time n is copy-initialized from arg }
在函数调用表达式中,非限定 函数名将按照称为 "参数依赖查找" (ADL) 的额外规则集进行查找。
函数可以是 协程,在这种情况下,它可以挂起执行,以便稍后恢复。 |
(自 C++20 起) |
函数声明 可以出现在任何作用域中,但 函数定义 只能出现在命名空间作用域中,对于 成员 函数和 友元 函数,则只能出现在类作用域中。在类体中声明而没有友元规范符的函数是类成员函数。此类函数具有许多附加属性,有关详细信息,请参阅 成员函数。
函数不是对象:没有函数数组,函数不能按值传递或从其他函数中返回。指向函数的指针和引用(除了 主函数 和 大多数标准库函数(自 C++20 起))是允许的,可以在无法使用函数本身的地方使用。因此,我们称这些函数是“可寻址的”。
每个函数都有一个类型,它包括函数的返回类型、所有参数的类型(在数组到指针和函数到指针转换之后,请参阅 参数列表) 、函数是否为 noexcept
(自 C++17 起),以及对于非静态成员函数,cv-限定符 和 ref-限定符(自 C++11 起)。函数类型还有 语言链接。没有 cv-限定的函数类型(不要与 cv-限定函数 的类型混淆,例如 int f() const; 或返回 cv-限定类型 的函数,例如 std::string const f();)。如果将任何 cv-限定符添加到函数类型的别名,则该限定符将被忽略。
同一个作用域中的多个函数可以具有相同的名称,只要它们的 parameter lists 和非静态成员函数的 cv/ref(自 C++11 起)-限定符不同即可。这被称为 函数重载。仅在返回类型 和 noexcept 规范(自 C++17 起) 上不同的函数声明不能重载。重载函数的地址 的确定方式不同。
C++ 使用 lambda 表达式 实现 匿名函数。 |
(自 C++11 起) |
[编辑] 函数对象
除了函数左值,函数调用表达式还支持指向函数的指针,以及任何重载函数调用运算符或可转换为函数指针的类类型值(包括 lambda表达式)(自 C++11 起)。这些类型统称为 函数对象,它们在整个 C++ 标准库中广泛使用,例如,二元谓词 和 比较器 的用法。
标准库还提供了一些预定义的 函数对象模板 以及用于组合新的函数对象的方法(包括 std::less, std::mem_fn, std::bind, std::function(自 C++11 起), std::not_fn(自 C++17 起), std::bind_front(自 C++20 起), std::bind_back, std::move_only_function(自 C++23 起), std::copyable_function, 和 std::function_ref(自 C++26 起))。