函数
函数是 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 说明符的类体中声明的函数是类成员函数。此类函数具有许多附加属性,请参阅成员函数以了解详细信息。
函数不是对象:没有函数数组,函数不能按值传递或从其他函数返回。允许使用指向函数的指针和引用(除了main 函数和大多数标准库函数(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 起))。