函数
函数是 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 起) |
函数声明可以出现在任何作用域中,但函数定义只能出现在命名空间作用域中,或者对于成员函数和友元函数,出现在类作用域中。在类体中声明且没有 friend 说明符的函数是类成员函数。此类函数具有许多额外的特性,详见成员函数。
函数不是对象:没有函数数组,函数不能按值传递或从其他函数返回。允许使用函数指针和引用(主函数和大多数标准库函数除外(C++20 起)),并且可以在函数本身无法使用的地方使用它们。因此我们说这些函数是“可寻址的”。
每个函数都有一种类型,由函数的返回类型、所有参数的类型(经过数组到指针和函数到指针的转换后,参见参数列表)、函数是否是noexcept
(C++17 起),以及对于非静态成员函数,cv-限定和引用限定(C++11 起)组成。函数类型还具有语言链接。不存在 cv-限定函数类型(不要与cv-限定函数的类型混淆,例如int f() const;,或返回cv-限定类型的函数,例如std::string const f();)。如果将任何 cv-限定符添加到函数类型的别名中,则该限定符将被忽略。
同一作用域中的多个函数可以具有相同的名称,只要它们的参数列表以及对于非静态成员函数,cv/ref(C++11 起)-限定不同即可。这称为函数重载。仅返回类型和 noexcept 规范(C++17 起)不同的函数声明不能重载。重载函数的地址以不同的方式确定。
C++ 使用lambda 表达式实现匿名函数。 |
(C++11 起) |
[编辑] 函数对象
除了函数左值,函数调用表达式还支持函数指针以及重载函数调用运算符或可转换为函数指针的任何类类型值(包括lambda 表达式)(C++11 起)。总的来说,这些类型被称为函数对象(FunctionObject),它们在 C++ 标准库中被广泛使用,例如,参见二元谓词(BinaryPredicate)和比较(Compare)的用法。
标准库还提供了许多预定义的函数对象模板以及组合新模板的方法(包括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 起))。