【C++】C++中的函数的基本使用
目录结构:
1.简介
通常函数包括形参,函数名,函数主体,函数返回值。下面的案例展示了c++函数使用的基本语法规则:
int add(int,int);//add函数的声明 int main(int argc,char *argv[]){ int res = add(1,1); return 0; } //add函数的定义 int add(int a,int b){ return a+b; }
也可以不用写add函数的声明,直接把的add函数的定义写在main函数的上面:
int add(int a,int b){//add函数的定义 return a+b; } int main(int argc,char *argv[]){ int res = add(1,1); return 0; }
2.可变形参的函数
c++支持可变形参的函数,可以使用initializer_list来实现或是省略符来实现。
2.1 initializer_list形参
如果函数的实参数量未知,但是全部的实参类型都相同,那么就可以使用initializer_list类型的形参。在使用initilizer_list类型之前,必需先引用<initilizer_list>头文件。
initializer_list是一种模板类型,应此在使用时必需说明所含元素的类型,例如:
initializer_list<string> ls; //initializer_list元素中的类型是string initializer_list<int> li; //initializer_list元素中的类型是int
注意:initializer_list对象中的元素值永远是常量,我们无法改变initializer_list对象中元素的值。
#include <iostream> #include <initializer_list> using namespace std; void error_msg(initializer_list il){ for(auto beg=il.begin(); beg != il.end(); beg++) cout << *beg << " "; cout << endl; } int main(int argc,char *argv[]){ error_msg({"error message 1","error message 2"});//调用error_msg函数 return 0; }
2.2 省略符形参
省略符形参只能用在形参列表的最后一个位置
例如:
#include <iostream> /*cout,endl*/ #include <cstdarg> /*va_list,va_start,va_end*/ int sum(int count, ...) { //格式:count代表参数个数, ...代表n个参数 va_list ap; //声明一个va_list变量 va_start(ap, count); //第二个参数表示形参的个数并且只能是参数列表中最后一个被命名了的参数。 int sum = 0; for (int i = 0; i < count; i++) { sum += va_arg(ap, int); //第二个参数表示形参类型 } va_end(ap); //用于清理 return sum; } int main(int argc,char **argv){ cout << sum(5,1.1,2.2,3.3,4.4,5.5) << endl; return 0; }
3.main函数处理命令行选项
main函数是应用程序的入口函数,它有如下几种形式:
int main(){} int main(int argv,char *argv[]){} int main(int argv,char **argv){}
第一种形式main函数不接收任何参数。
第二种形式main函数,其中第一个形参argc表示数组的大小;第二个形参argv表示一个数组,它的元素是指向C风格字符串的指针。
int main(int argc,char *argv[]){ for(decltype(argc) index=0; index<argc; index++) cout << argv[index] << " "; cout << endl; return 0; }
第三种形式main函数,argv是一个指针,指向一个char*类型。
int main(int argc,char **argv){ for(decltype(argc) index=0; index<argc; index++) cout << (*argv++) << " "; cout << endl; return 0; }
若将上面的程序命名为test.cpp,在编译成功后,使用如下命令运行:./test how are you
输出结果为:
./test how are you
从结果中可以看出,"./test"并不是我们想输出的(我们本意是想输出"how are you")。应此需要注意,main函数中,实际的参数应该从下标1开始。
4.函数指针与函数引用
函数指针,顾名思义就是指向函数的指针。同理,函数引用就是引用函数的引用。
例如:
bool (*pf)(const string&,const string&);
pf前面有一个*,因此pf是指针;右侧是形参列表,表明pf指向函数;再观察左侧,发现函数的返回值类型是布尔值。因此pf就是一个指向函数的指针,其中函数具有两个const string&形参,返回值是bool类型。
注意:
如果pf是这样的话
bool *pf(const string&,const string&)
那么pf就不是函数指针了,这种情况下pf表示为一个函数,函数具有两个const string&类型的形参,和一个bool指针类型的返回值。
当把函数名作为一个值使用时,该函数自动地转化为指针。同时还能直接使用指向函数的指针调用该函数,无须提前解引用。
#include <iostream> /*cout,endl*/ using namespace std; int compare(const string& a,const string& b){ return a.compare(b); } int compare(const int& a,const int& b){ return a - b; } //定义一个函数,其形参为另一个函数 void test1(int (*p)(const string&,const string&)){ p("hello","world"); }; //test2和test1是等价声明,函数类型会自动转化为指向函数的指针 void test2(int p(const string&,const string&)){ p("hello","world"); }; //test3返回一个函数指针,该指针具有两个int类型的形参,返回值类型为void void (*test3())(int,int){ } //test4和test3是等价声明 auto test4()-> void (*)(int,int){ } void (*test5( int (*p)(const int&,const int&) ))(int,int){ p(1,2); return 0; } int main(int argc,char **argv){ int (*pf)(const string&,const string&);//声明一个函数指针 pf=0;//pf不指向任何函数 pf = compare;//pf指向 int compare(const string&,const string&) int res = pf("hello","world");//调用pf所知指函数,无需提前解引用 int (&rpf)(const int&,const int&) = compare;//声明一个引用,初始化为compare(compare有两个重载函数,这里引用形参为两个的const int&的函数) int res = rpf(1,2);//调用rpf所引用的函数 test1(compare);//传递方法作为实参,也可以参数函数指针作为实参。 void (*p)(int,int) = test3();//返回一个函数指针 p = test5(rpf);//接受一个函数指针,返回一个函数指针。rpf会自动转化为函数指针 return 0; }
5.inline内联函数
inline函数被称为内联函数,就是将它在每个调用的节点上“内联地”展开。
在函数定义的时候加上inline关键字,这样就成为内联函数了。
#include <iostream> #include <string> using namespace std; //shoterString函数接受两个const string类型参数,返回一个const string&类型的数据,同时该函数是内联函数。 inline const string & shoterString(const String s1,const String s2){ return (s1.size() < s2.size() ? s1 : s2); } int main(int argc,char *argv[]){ string s1 = "hello"; string s2 = "world"; //编译时转化为cout << (s1.size() < s2.size() ? s1 : s2) << endl; cout << shoterString(s1,s2) << endl; }
一般来说,内联机制用于规模较小,流程直接,频繁调用的函数。很多编译器都不支持内联递归函数。
6.Constexpr函数
constexpr是c++11新标准添加的关键字,该关键字主要用于提供程序的运行效率,使用constexpr指定的值和函数能够在编译时进行计算,比如下面的product()将会在编译时被计算:
constexpr int product(int x, int y) { return (x * y); } int main() { //在编译后,会直接转化为 const int x = 200; const int x = product(10, 20); cout << x; return 0; }
输出结果为:
200
使用constexpr函数有以下几点约束:
1.在c++11中,一个constexpr函数只能有一个return语句。c++14标准中,允许超过一个return语句。
2.constexpr函数应该只引用常量全局变量
3.constexpr函数能够调用其他constexpr函数,不能调用非constexpr函数。
4.constexpr函数不能返回void类型,还有一些操作符比如(++v,--v)都不允许出现在constexpr函数。