C++基础知识【4】函数及参数
创始人
2024-05-30 02:12:50
0

目录

一、函数的基本概念

1.1、构成

1.2、声明和定义

1.3、函数的调用

二、参数

2.1、形参和实参

2.2、参数的传递

传值

传引用

传指针

三、C++函数的一些新特性

3.1、Lambda表达式

3.2、右值引用

3.3、默认参数

3.4、变长参数模板

3.5、constexpr函数

3.6、noexcept函数

四、C++内联函数

五、函数的重载


一、函数的基本概念

        C++函数是一段可重用的代码,用于执行特定的任务。它可以接受输入参数、执行一些操作,最后返回一个值。函数可以通过模块化编程来简化代码,提高代码的可读性和可维护性。函数也被称作方法。

        函数分为库函数(也称标准函数库或系统函数库)和自定义函数两种。

        库函数是指在C++标准库或其他系统库中提供的函数,通常包含在头文件中。C++标准库中包含了很多常用的函数和数据类型,例如字符串处理、输入输出、数学计算、容器和算法等等。开发者可以直接使用这些库函数,而无需重新编写代码,从而提高开发效率和代码可读性。

        自定义函数是由开发者自行编写的函数,用于实现特定的功能。自定义函数可以在程序中多次调用,避免了代码的重复编写。自定义函数的定义可以在main函数之前或之后,甚至在其他文件中,只要在使用函数之前有函数声明即可。

        本文主要解释自定义函数。

1.1、构成

        函数的构成:

返回类型 函数名(参数列表) {函数体return 返回值;}

其中:

  • 函数名:函数名是函数的标识符,用于标识函数并区分其他函数。在C++中,函数名由字母、数字和下划线组成,不能以数字开头。
  • 参数列表:参数列表是一组用逗号分隔的变量,函数在执行时需要这些变量的值。C++中的函数可以有零个或多个参数,参数可以有默认值,也可以是引用类型。
  • 返回类型:返回类型指定函数返回的值的类型。C++中的函数可以返回任何类型的值,包括基本数据类型、结构体、类、指针等。
  • 函数体:函数体是包含一组语句的代码块,它定义了函数要执行的操作。

1.2、声明和定义

        函数可以先声明再定义,或者直接定义。函数的声明和定义可以分别在不同的源文件中实现,这种方式可以方便地实现模块化编程和代码复用。

        函数声明:函数声明通常包括函数名、参数列表和返回类型,它告诉编译器这个函数的存在和类型,以便编译器在调用该函数时能够正确地生成调用代码。函数声明可以出现在头文件中,也可以在函数定义之前进行。

        函数定义:函数定义包括函数名、参数列表、返回类型和函数体,它实现了函数的具体功能。函数定义必须出现在程序的某个位置,通常放在源文件的末尾。

以下是一个使用函数声明和定义的例子:

// 声明函数int addFun(int x, int y);// 定义函数int addFun(int x, int y) {return x + y;}

1.3、函数的调用

        C++函数通过函数名和参数列表来调用。调用函数时,需要将实际参数传递给函数。实际参数是调用函数时提供的参数。

以下是调用函数的语法:

函数名(实际参数列表);

例如,要调用上面定义的 addFun 函数,可以这样写:

int main() {int a = 10, b = 20;int c = addFun(a, b);return 0;}

二、参数

2.1、形参和实参

        C++函数的参数分为形式参数和实际参数。形式参数是定义在函数声明或定义中的参数,也称为形参。实际参数是在调用函数时传递给函数的值或变量,也称为实参。

        需要注意的是,函数的实参可以是常量、变量、表达式、指针、引用等类型,而函数的形参通常是变量或引用类型。在函数调用时,实参会被传递给形参,如果实参和形参的类型不匹配,编译器会尝试进行类型转换。如果无法进行类型转换,编译器将会报错。

        此外,C++还支持默认参数,它允许在函数定义时为某些参数设置默认值,这样在函数调用时可以省略这些参数。例如:

int addFun(int a, int b = 0) {return a + b;}int main() {int x = 10, y = 20;int result1 = addFun(x); // b参数使用默认值0int result2 = addFun(x, y); // b参数使用传递的实参yreturn 0;}

2.2、参数的传递

        C++支持三种参数传递方式:传值、传引用或传指针。

传值

        传值是将实际参数的值复制到形式参数的过程。在函数中修改形式参数的值不会影响实际参数的值。这种方式适用于参数较少、参数类型简单的情况,也是使用最广泛的情况。

以下是传值调用的示例:

void addplus(int a) {a++; // 修改形式参数的值}int main() {int x = 10;addplus(x); // 传递 x 的值cout << x << endl; // 输出 10,x 的值没有改变return 0;}

传引用

        传引用是指将实参的地址传递给形参,函数内部可以直接操作实参的值。传引用方式可以避免复制大量的数据,提高程序的效率。传引用方式使用引用符号 & 定义形参。

以下是传引用的示例:

void addplus(int& a) {a++; // 通过引用修改实际参数的值}int main() {int x = 10;addplus(x); // 传递 x 的别名cout << x << endl; // 输出 11,x 的值已经被修改return 0;}

传指针

        传指针是指将实参的地址传递给形参,函数内部可以通过指针来操作实参的值。传指针方式可以与传引用方式相比,更加灵活,但需要注意指针为空的情况。传指针方式使用指针符号 * 定义形参。

以下是传指针的示例:

void addplus(int* a) {(*a)++; // 通过指针修改实际参数的值
}int main() {int x = 10;addplus(&x); // 传递 x 的地址cout << x << endl; // 输出 11,x 的值已经被修改return 0;
}

注意,传引用通常比传指针更易于使用和更安全,因为它可以防止空指针异常。

三、C++函数的一些新特性

3.1、Lambda表达式

        Lambda表达式是一种匿名函数,可以在需要时快速创建一个函数对象。Lambda表达式可以访问它所在函数的变量,这使得它们非常灵活和有用。

以下是一个使用Lambda表达式的例子:

#include 
#include 
#include int main() {std::vector nums = {1, 2, 3, 4, 5};std::for_each(nums.begin(), nums.end(), [](int num) {std::cout << num << " ";});return 0;
}

        在这个例子中,Lambda表达式被传递给了std::for_each算法,用于输出向量中的所有元素。Lambda表达式的参数类型和返回类型都可以被自动推断出来。

3.2、右值引用

        右值引用是一种新的引用类型,可以将右值转换为左值,并提高代码的性能和效率。

以下是一个使用右值引用的例子:

#include 
#include std::string&& foo(std::string& str) {return std::move(str);
}int main() {std::string str = "hello, world!";std::string&& rstr = foo(str);std::cout << rstr << std::endl;return 0;
}

        在这个例子中,foo函数返回一个右值引用,将传递给它的字符串转换为右值。在main函数中,我们使用一个右值引用变量来接收foo函数的返回值,并输出它。

3.3、默认参数

        默认参数允许在函数定义中为某些参数设置默认值,在函数调用时可以省略这些参数。

以下是一个使用默认参数的例子:

#include 
#include void foo(std::string str = "hello, world!") {std::cout << str << std::endl;
}int main() {foo(); // 输出:hello, world!foo("hi, there!"); // 输出:hi, there!return 0;
}

在这个例子中,foo函数的参数str被设置了默认值"hello, world!"。当我们在main函数中调用foo函数时,如果不传递任何参数,则使用默认值;否则,使用传递的参数值。

3.4、变长参数模板

        可变参数模板允许在函数中使用任意数量的参数,这对于处理不定数量的参数非常有用。

以下是一个使用可变参数模板的例子:

#include 
#include template 
void print(T arg) {std::cout << arg << std::endl;
}template 
void print(T arg, Args... args) {std::cout << arg << " ";print(args...);
}int main() {print("hello", "world", "!");print(1, 2, 3, 4, 5);return 0;
}

3.5、constexpr函数

        constexpr函数是一种特殊的函数,可以在编译时求值,这可以提高程序的效率和性能。

以下是一个使用constexpr函数的例子:

#include constexpr int factorial(int n) {return n <= 1 ? 1 : n * factorial(n - 1);
}int main() {constexpr int n = 5;constexpr int result = factorial(n);std::cout << result << std::endl;return 0;
}

3.6、noexcept函数

        noexcept函数是一种指定函数不抛出异常的方法,这可以帮助编译器优化代码并提高程序的性能。

以下是一个使用noexcept函数的例子:

#include 
#include void foo(std::vector& v) noexcept {v.push_back(42);
}int main() {std::vector v = {1, 2, 3};foo(v);for (auto i : v) {std::cout << i << " ";}return 0;
}

四、C++内联函数

        C++中,内联函数是一种特殊的函数,编译器会尝试将其在调用点直接展开,以避免函数调用的开销。

        内联函数通常是通过在函数定义前加上inline关键字来定义的。在调用内联函数时,编译器会直接将函数体插入到调用点处,而不会生成函数调用的代码。这种展开的方式可以减少函数调用的开销,从而提高程序的性能。

        需要注意的是,内联函数适用于函数体比较简单的函数。对于函数体比较复杂的函数,内联展开可能会导致代码膨胀,反而降低程序的性能。此外,编译器并不一定会将函数展开为内联函数,具体是否展开取决于编译器的实现。

下面是一个内联函数的例子:

inline int add(int a, int b) {return a + b;}

        需要注意的是,内联函数仅仅是一种建议,编译器并不一定会将其展开为内联函数。

        此外,对于在类定义中定义的成员函数,默认情况下也是内联函数,类定义中定义的成员函数会隐式地添加inline关键字。因此,对于类定义中定义的成员函数,不需要显式地添inline关键字。

五、函数的重载

        C++中,函数重载(Function Overloading)指的是在同一个作用域内定义的具有相同名称但参数类型、个数或顺序不同的多个函数。在调用函数时,编译器会根据实参的类型、个数和顺序,自动选择合适的函数进行调用。

        函数重载的优点在于可以方便地为函数提供不同的参数选项,同时能够避免函数名称冲突的问题。

下面是一个函数重载的例子:

int add(int a, int b) {return a + b;}double add(double a, double b) {return a + b;}int add(int a, int b, int c) {return a + b + c;}

        需要注意的是,函数重载的区分是基于参数类型、个数和顺序的,而不是基于返回值类型的。因此,在定义函数时,不能只依据返回值类型的不同来进行函数重载。

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...