C++基础功能-函数

1 函数

1.1 函数定义

函数:函数的名字;参数列表,可以为空();返回类型,可以是void,可前置或者后置(使用auto)。inline,是一种愿望:通过内联函数整体实现函数调用。constexpx,表示当给定常量表达式作为实参时,可以在编译时对函数求值。noexcept,表示该函数不允许抛出异常。链接说明:例如static。[[noreturn]],表示该函数不会常规的调用/返回机制返回结果。此外,成员函数还能被限定为:virtual,该函数可以被派生类覆盖。override,该函数必须覆盖基类中的一个虚函数。final,该函数不能被派生类覆盖。static,该函数不与某一特定对象关联。const,该函数不能修改其对象的内容。

void swap(int* , int* )
void swap(int* p,int* q)
{
int t=*p;
*p=*q;
*q=t;
}

1.2 函数返回值

string to_string(int a); //前置返回类型
auto to_string(int a) -> string ; //后置返回类型
前置的关键词auto表示函数的返回类型放在参数列表之后,由->符号引导。

并不存在void值,但是可以调用void函数令其作为另一个void函数的返回值。

void g(int* p)
void h(int* p)
{
//....
return g(p);
}

inline int fac(int n)
{
return (n<2)? 1: n*fac(n-1)
}

inline函数:inline限定符告诉编译器,尝试为fac()调用内联代码,而非为fac()函数构建代码再通过常规的调用机制调用它。

constexpr出现在函数定义中时,它的含义是“如果给定了常量表达式作为实参,则该函数应该能用在常量表达式中”。而当constexpr出现在对象定义中时,它的含义是在编译时对初始化器求值。函数必须足够简单才能在编译时求值。constexpr函数必须包含一条独立的return语句,不能有循环,也没有局部变量,constexpr函数不能有副作用。

1.3 局部变量

当线程执行到局部变量时,它们将被初始化,除非我们把变量声明成static,否则函数的每次调用都会拷贝一次该变量。

void f(int a)
{
while(a--){
static int n=0;
int x=0;
cout<<"n == "<<n++<<",x == "<<x++<<"\n";
}
}
int main()
{
f(3);
}

static局部变量可以在函数的多次调用间维护一份公共信息,而无须使用全局变量。

2 参数传递

当程序调用一个函数时,我们为该函数的形参申请内存空间,并用实参初始化对应的形参。编译器负责检查实参的类型是否对应形参类型,并在必要时进行标准类型转换或者自定义类型转换。除非形参是引用,其他情况下传入函数的是实参的副本。

2.1 引用参数

两种方式,一种以值的方式传入函数,另一种以传引用的方式传入函数。

void f(const Large&arg)
{
//不允许修改“arg”的值。
}

如果未被指定const,则可以修改该参数的值。类似的指针类型的参数被声明成const意味着该指针所指的对象的值不会被函数改变。

int strlen(cosnt char*);
char* strcpy(char* to,const char* from);
int strcmp(cosnt char* ,cosnt char*);

字面值、常量和需要执行类型转换的参数可以传递给const T&参数,但是不能传给普通的非const T&参数。

float fsqrt(const float&);
void g(double d)
{
float r=fsqrt(2.0f);		//传递存放2.0f的临时变量的引用;
r=fsqrt(r);				//传递r的引用
r=fsqrt(d);			//传递存放static_cast<float>(d)的临时变量的引用
}

2.2 数组参数

当数组作为函数的参数时,实际传入的是指向该数组首元素的指针。数组类型的参数与指针类型的参数等价。
void odd(int *p);
void odd(int a[]);
void odd(int buf[1024]);

数组的尺寸可以表示为:
void compute1(int* vec_ptr,int vec_size);

2.3 列表参数

类型std::initializer_list,其中列表的值能隐式的转换为T。

2.4 默认参数

int f(int,int =0,char* =nullptr);

3 重载函数

不同函数在不同类型的对象上执行相同的任务,则给它们起同一名字是更好的选择,为不同的数据类型的同一种操作起相同的名字称为重载。
3.1 自动重载解析
当调用函数f时,由编译器决定使用名为f的那组函数时,依据是考察实参类型与作用域中名为f的哪个函数的形参类型最为匹配。

void print(double)
void print(long)

void f()
{
print(1L);
print(1.0);
print(1);
}

重载解析过程中不考虑函数的返回类型,这样可以确保对运算符或者函数调用的解析独立于上下文。

3.2 重载和作用域

重载函数应该位于同一作用域内,不同的非名字空间作用域中的函数不会重载。

void f(int)

void g()
{
void f(double)
f(1);			//调用f(double)
}

struct Base{
void f(int);
};

struct Derived:Base{
void f(double);
};

void g(Derived & d)
{
	d.f(1);		//调用Derived::f(double);
}

4 前置条件和后置条件
5 函数指针
通过获取函数地址得到的指针能被用来调用该函数。函数指针的参数类型声明与函数本身类似,进行指针赋值操作时,要求完整的函数类型必须精确匹配。

void (*pf)(string);	//指向void(string)的指针
void f1(string);		//void(string)
int f2(string);		//int(string)
void f3(int*);		//void(int*)

void f()
{
pf=&f1;		//正确;
pf=&f2;		//错误,返回类型错误;
pf=&f3;		//错误,参数类型错误;

pf("Hera");		//正确
pf(1);		//错误,参数类型错误;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值