菜鸟教程 -- 学的不仅是技术,更是梦想!

C++ 教程
C++ 教程 C++ 简介 C++ 环境设置 C++ 基本语法 C++ 注释 C++ 数据类型 C++ 变量类型 C++ 变量作用域 C++ 常量 C++ 修饰符类型 C++ 存储类 C++ 运算符 C++ 循环 C++ 判断 C++ 函数 C++ 数字 C++ 数组 C++ 字符串 C++ 指针 C++ 引用 C++ 日期 & 时间 C++ 基本的输入输出 C++ 结构体(struct) C++ vector 容器 C++ 数据结构

C++ 面向对象

C++ 类 & 对象 C++ 继承 C++ 重载运算符和重载函数 C++ 多态 C++ 数据抽象 C++ 数据封装 C++ 接口(抽象类)

C++ 高级教程

C++ 文件和流 C++ 异常处理 C++ 动态内存 C++ 命名空间 C++ 模板 C++ 预处理器 C++ 信号处理 C++ 多线程 C++ Web 编程

C++ 资源库

C++ STL 教程 C++ 导入标准库 C++ 标准库 C++ 有用的资源 C++ 实例 C++ 测验 C++ <iostream> C++ <fstream> C++ <sstream> C++ <iomanip> C++ <array> C++ <vector> C++ <list> C++ <forward_list> C++ <deque> C++ <stack> C++ <queue> C++ <priority_queue> C++ <set> C++ <unordered_set> C++ <map> C++ <unordered_map> C++ <bitset> C++ <algorithm> C++ <iterator> C++ <functional> C++ <numeric> C++ <complex> C++ <valarray> C++ <cmath> C++ <string> C++ <regex> C++ <ctime> C++ <chrono> C++ <thread> C++ <mutex> C++ <condition_variable> C++ <future> C++ <atomic> C++ <type_traits> C++ <typeinfo> C++ <exception> C++ <stdexcept> C++ <cstdio> C++ <cstdint> C++ <memory> C++ <new> C++ <utility> C++ <random> C++ <locale> C++ <codecvt> C++ <cassert> C++ <cwchar> C++ <climits> C++ <cfloat> C++ <cstdlib> C++ <numbers> C++ OpenCV
(追記) (追記ここまで)

C++ 函数

函数是一组一起执行一个任务的语句。每个 C++ 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。

您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的,但在逻辑上,划分通常是根据每个函数执行一个特定的任务来进行的。

函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实际主体。

C++ 标准库提供了大量的程序可以调用的内置函数。例如,函数 strcat() 用来连接两个字符串,函数 memcpy() 用来复制内存到另一个位置。

函数还有很多叫法,比如方法、子例程或程序,等等。

定义函数

C++ 中的函数定义的一般形式如下:

return_typefunction_name(parameterlist){bodyofthefunction}

在 C++ 中,函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分:

  • 返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void
  • 函数名称:这是函数的实际名称。函数名和参数列表一起构成了函数签名。
  • 参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
  • 函数主体:函数主体包含一组定义函数执行任务的语句。

实例

以下是 max() 函数的源代码。该函数有两个参数 num1 和 num2,会返回这两个数中较大的那个数:

// 函数返回两个数中较大的那个数intmax(intnum1, intnum2){// 局部变量声明intresult; if(num1 > num2)result = num1; elseresult = num2; returnresult; }

函数声明

函数声明会告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。

函数声明包括以下几个部分:

return_type function_name( parameter list );

针对上面定义的函数 max(),以下是函数声明:

int max(int num1, int num2);

在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:

int max(int, int);

当您在一个源文件中定义函数且在另一个文件中调用函数时,函数声明是必需的。在这种情况下,您应该在调用函数的文件顶部声明函数。

调用函数

创建 C++ 函数时,会定义函数做什么,然后通过调用函数来完成已定义的任务。

当程序调用函数时,程序控制权会转移给被调用的函数。被调用的函数执行已定义的任务,当函数的返回语句被执行时,或到达函数的结束括号时,会把程序控制权交还给主程序。

调用函数时,传递所需参数,如果函数返回一个值,则可以存储返回值。例如:

实例

#include<iostream>usingnamespacestd; // 函数声明intmax(intnum1, intnum2); intmain(){// 局部变量声明inta = 100; intb = 200; intret; // 调用函数来获取最大值ret = max(a, b); cout << "Max value is : " << ret << endl; return0; }// 函数返回两个数中较大的那个数intmax(intnum1, intnum2){// 局部变量声明intresult; if(num1 > num2)result = num1; elseresult = num2; returnresult; }

把 max() 函数和 main() 函数放一块,编译源代码。当运行最后的可执行文件时,会产生下列结果:

Max value is : 200

函数参数

如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数

形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。

当调用函数时,有三种向函数传递参数的方式:

调用类型描述
传值调用 该方法把参数的实际值赋值给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。
指针调用 该方法把参数的地址赋值给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
引用调用 该方法把参数的引用赋值给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。

默认情况下,C++ 使用传值调用来传递参数。一般来说,这意味着函数内的代码不能改变用于调用函数的参数。之前提到的实例,调用 max() 函数时,使用了相同的方法。

参数的默认值

当您定义一个函数,您可以为参数列表中后边的每一个参数指定默认值。当调用函数时,如果实际参数的值留空,则使用这个默认值。

这是通过在函数定义中使用赋值运算符来为参数赋值的。调用函数时,如果未传递参数的值,则会使用默认值,如果指定了值,则会忽略默认值,使用传递的值。请看下面的实例:

实例

#include<iostream>usingnamespacestd; intsum(inta, intb=20){intresult; result = a + b; return(result); }intmain(){// 局部变量声明inta = 100; intb = 200; intresult; // 调用函数来添加值result = sum(a, b); cout << "Total value is :" << result << endl; // 再次调用函数result = sum(a); cout << "Total value is :" << result << endl; return0; }

当上面的代码被编译和执行时,它会产生下列结果:

Total value is :300
Total value is :120

Lambda 函数与表达式

C++11 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。

Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。

Lambda 表达式本质上与函数声明非常类似。Lambda 表达式具体形式如下:

[capture](parameters)->return-type{body}

例如:

[](int x, int y){ return x < y ; }

如果没有返回值可以表示为:

[capture](parameters){body}

例如:

[]{ ++global_x; } 

在一个更为复杂的例子中,返回类型可以被明确的指定如下:

[](int x, int y) -> int { int z = x + y; return z + x; }

本例中,一个临时的参数 z 被创建用来存储中间结果。如同一般的函数,z 的值不会保留到下一次该不具名函数再次被调用时。

如果 lambda 函数没有传回值(例如 void),其返回类型可被完全忽略。

在Lambda表达式内可以访问当前作用域的变量,这是Lambda表达式的闭包(Closure)行为。 与JavaScript闭包不同,C++变量传递有传值和传引用的区别。可以通过前面的[]来指定:

[] // 沒有定义任何变量。使用未定义变量会引发错误。
[x, &y] // x以传值方式传入(默认),y以引用方式传入。
[&] // 任何被使用到的外部变量都隐式地以引用方式加以引用。
[=] // 任何被使用到的外部变量都隐式地以传值方式加以引用。
[&, x] // x显式地以传值方式加以引用。其余变量以引用方式加以引用。
[=, &z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用。

另外有一点需要注意。对于[=]或[&]的形式,lambda 表达式可以直接使用 this 指针。但是,对于[]的形式,如果要使用 this 指针,必须显式传入:

[this]() { this->someFunc(); }();
AI 思考中...

10 篇笔记 写笔记

  1. #0

    lqd052

    172***[email protected]

    338

    Lambda 函数与表达式

    Lambda函数的语法定义如下:

    [capture](parameters) mutable ->return-type{statement}

    其中:

    • [capture]:捕捉列表。捕捉列表总是出现在 lambda 表达式的开始处。事实上,[] 是 lambda 引出符。编译器根据该引出符判断接下来的代码是否是 lambda 函数。捕捉列表能够捕捉上下文中的变量供 lambda 函数使用。
    • (parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号 () 一起省略。
    • mutable:mutable 修饰符。默认情况下,lambda 函数总是一个 const 函数,mutable 可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空)。
    • ->return_type:返回类型。用追踪返回类型形式声明函数的返回类型。出于方便,不需要返回值的时候也可以连同符号 -> 一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导。
    • {statement}:函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。

    在 lambda 函数的定义式中,参数列表和返回类型都是可选部分,而捕捉列表和函数体都可能为空,C++ 中最简单的 lambda 函数只需要声明为:

    []{};

    lqd052

    172***[email protected]

    9年前 (2017年07月24日)
  2. #0

    两个实际应用到lambda表达式的代码。

    std::vector<int> v = { 1, 2, 3, 4, 5, 6 };
    int even_count = 0;
    for_each(v.begin(), v.end(), [&even_count](int val){
     if(!(val & 1)){
     ++ even_count;
     }
    });
    std::cout << "The number of even is " << even_count << std::endl;
    
    int count = std::count_if( coll.begin(), coll.end(), [](int x){ return x > 10; }); 
     
    int count = std::count_if( coll.begin(), coll.end(), [](int x){ return x < 10; }); 
     
    int count = std::count_if( coll.begin(), coll.end(), [](int x){ return x > 5 && x<10; }); 
    
    9年前 (2017年09月07日)
  3. #0

    prigioni

    763***[email protected]

    91

    定义一个可以输出字符串的lambda表达式,表达式一般都是从方括号[]开始,然后结束于花括号{},花括号里面就像定义函数那样,包含了lamdba表达式体:

    // 定义简单的lambda表达式
    auto basicLambda = [] { cout << "Hello, world!" << endl; };
    // 调用
    basicLambda();
    // 输出:Hello, world!

    如果需要参数,那么就要像函数那样,放在圆括号里面,如果有返回值,返回类型要放在->后面,即拖尾返回类型,当然你也可以忽略返回类型,lambda会帮你自动推断出返回类型:

    // 指明返回类型
    auto add = [](int a, int b) -> int { return a + b; };
    // 自动推断返回类型
    auto multiply = [](int a, int b) { return a * b; };
    int sum = add(2, 5); // 输出:7
    int product = multiply(2, 5); // 输出:10

    prigioni

    763***[email protected]

    9年前 (2017年10月15日)
  4. #0

    eric

    gxy***@163.com

    135

    Lambda函数很简洁,但变化较多。

    1、什么也不捕获,或者是故意不用 Lambda 函数外部的变量

    #include <iostream>
    using namespace std;
     
    int main()
    {
     int i = 1024;
     auto func = [] { cout << i; };
     func();
    } // 结果报错,因为未指定默认捕获模式

    正确的如下:

    #include <iostream>
    using namespace std;
     
    int main()
    {
     int i = 1024;
     auto func = [=]{ // [=] 表明将外部的所有变量拷贝一份到该Lambda函数内部
     cout << i;
     };
     func();
    }

    2、引用捕获

    #include <iostream>
    using namespace std;
     
    int main()
    {
     int i = 1024;
     cout << &i << endl;
     auto fun1 = [&]{
     cout << &i << endl;
     };
     fun1();
    }

    3、复制并引用捕获

    #include <iostream>
    using namespace std;
     
    int main()
    {
     int i = 1024, j = 2048;
     
     cout << "i:" << &i << endl;
     cout << "j:" << &j << endl;
     
     auto fun1 = [=, &i]{ // 默认拷贝外部所有变量,但引用变量 i
     cout << "i:" << &i << endl;
     cout << "j:" << &j << endl;
     };
     fun1();
    }

    4、指定引用或复制

    #include <iostream>
    using namespace std;
     
    int main()
    {
     int i = 1024, j = 2048;
     
     cout << "outside i value:" << i << " addr:" << &i << endl;
     
     auto fun1 = [i]{
     cout << "inside i value:" << i << " addr:" << &i << endl;
     // cout << j << endl; // j 未捕获
     };
     fun1();
    }

    5、捕获this指针

    #include <iostream>
    using namespace std;
     
    class test
    {
    public:
     void hello() {
     cout << "test hello!n";
     };
     void lambda() {
     auto fun = [this]{ // 捕获了 this 指针
     this->hello(); // 这里 this 调用的就是 class test 的对象了
     };
     fun();
     }
    };
     
    int main()
    {
     test t;
     t.lambda();
    }

    eric

    gxy***@163.com

    9年前 (2017年12月27日)
  5. #0

    突然的幸福

    292***[email protected]

    108
    • []:默认不捕获任何变量;
    • [=]:默认以值捕获所有变量;
    • [&]:默认以引用捕获所有变量;
    • [x]:仅以值捕获x,其它变量不捕获;
    • [&x]:仅以引用捕获x,其它变量不捕获;
    • [=, &x]:默认以值捕获所有变量,但是x是例外,通过引用捕获;
    • [&, x]:默认以引用捕获所有变量,但是x是例外,通过值捕获;
    • [this]:通过引用捕获当前对象(其实是复制指针);
    • [*this]:通过传值方式捕获当前对象;

    突然的幸福

    292***[email protected]

    8年前 (2018年03月30日)
  6. #0

    突然的幸福

    292***[email protected]

    41

    lambda表达式无法修改通过复制形式捕捉的变量,因为函数调用运算符的重载方法是const属性的。有时候,你想改动传值方式捕获的值,那么就要使用mutable,例子如下:

    int main()
    {
     int x = 10;
     auto add_x = [x](int a) mutable { x *= 2; return a + x; }; // 复制捕捉x
     cout << add_x(10) << endl; // 输出 30
     return 0;
    }

    突然的幸福

    292***[email protected]

    8年前 (2018年03月30日)
  7. #0

    hanxiaolong2333

    320***[email protected]

    31

    编程语言中,函数直接或间接调用函数本身,则该函数称为递归函数。

    #include <iostream>
    using namespace std;
    // 本程序用递归算法求n的阶乘
    int counter=1;
    int fac(int n)
    {
     cout<<"第"<<counter<<"次调用:"<<n<<" * "<<"fac("<<n-1<<")"<<endl;
     if (n==1) {
     return 1;
     }
     else
     { 
     counter++;
     return n * fac(n-1); // 断点1
     }
    }
    int main()
    { 
     int n;
     cout<<"请输入求n的阶乘的n值:";
     cin>>n;
     cout<<"结果:fac("<<n<<")="<<fac(n)<<endl;
    }

    hanxiaolong2333

    320***[email protected]

    8年前 (2019年01月09日)
  8. #0

    Buktop

    931***[email protected]

    56

    一个新手可能会犯的错误

    由于在实际写代码过程中,可能会与到函数的定义和声明不在同一文件,声明出现在头文件中的情况

    这时,对带默认值的函数在声明和定义时,需要注意,默认值出现在声明的代码中,定义中不能再对参数赋与默认值,否则会报错。

    <Plus.h> //声明在头文件中
    int Plus(int a, int b = 10)
    <Plus.cpp>//定义在cpp文件中
    int Plus(int a, int b)//不能再对b赋值了
    {
     return a + b;
    }

    Buktop

    931***[email protected]

    6年前 (2020年09月19日)
  9. #0

    VALUE

    phj***[email protected]

    28

    函数必须声明才能使用:

    #include <iostream>
    #include<limits>
    using namespace std;
    //float area(float a,float b);
    int main()
    {
     
     float length,width;
     length=10.0;
     width=5.0;
     float areas=area(length,width);
     cout << areas <<endl;
     return 0;
    }
    float area(float a,float b){
     return a*b;
    }

    报错:

    main.cpp: In function ‘int main()’:
    main.cpp:11:14: error: ‘area’ was not declared in this scope; did you mean ‘areas’?
     11 | float areas=area(length,width);
     | ^~~~
     | areas

    正确做法:

    #include <iostream>
    #include<limits>
    using namespace std;
    float area(float a,float b);// 声明函数
    int main()
    {
     
     float length,width;
     length=10.0;
     width=5.0;
     float areas=area(length,width);// 调用函数
     cout << areas <<endl;
     return 0;
    }
    // 定义函数
    float area(float a,float b){
     return a*b;
    }

    运行结果:

    50

    VALUE

    phj***[email protected]

    6年前 (2020年12月18日)
  10. #0

    2020年7月11日

    191***[email protected]

    13

    特殊说明

    [this]: 通过引用捕获当前对象(对象本身)

    [*this]: 通过传值捕获当前对象(对象拷贝,且只是一个地址值,可以说没有意义)

    举例说明:

    #include <iostream>
    using namepsace std;
    //定义一个类
    class MM 
    {
    public:
     void print() {}
    };
    int main()
    {
     MM mm;
     //打印对象地址作对比
     cout << "对象本身地址:" << &mm << endl;
     
     [&mm](){cout << "[&mm]: " << &mm << endl;}(); //相当于[this]
     [mm](){cout << "[mm]: " << &mm << endl;}(); //相当于[*this]
     [mm](){cout << "[mm]: " << &mm << endl;}(); //相当于[*this]
     return 0;
    }

    结果:

    对象本身地址:012FF984
    [&mm]: 012FF984
    [mm]: 012FF878
    [mm]: 012FF850

    尝试将捕获的指针调用成员函数:

    [&mm](){cout << this->print();}(); //相当于[this]
    //[mm](){cout << this->print();}(); //相当于[*this],无法调用,因为传入的只是一个值

    2020年7月11日

    191***[email protected]

    4年前 (2022年07月11日)

点我分享笔记

  • 昵称 (必填)
  • 邮箱 (必填)
  • 引用地址

AltStyle によって変換されたページ (->オリジナル) /