从C到Cpp——八、Cpp的强大函数特性(一)

一、内联函数技术

内联函数是和普通函数原理不同的函数。普通函数调用时依据的是函数指针的寻址,将程序跳到函数定义中执行;而内联函数则是将函数调用都用函数定义覆盖。

内联函数有更高的执行效率,但会占用更多的空间。

要使用内联函数,请使用下面两种写法的至少一种:

1、在函数声明时先写上inline限定符

#include <iostream>
inline double square(double num);
int main(void)
{
	double a;
	std::cin>>a;
	std::cout<<square(a);
} 
double square(double num)
{
	return num*num;
}

2、在函数定义时先写上inline限定符

#include <iostream>

inline double square(double num)
{
	return num*num;
}

int main(void)
{
	double a;
	std::cin>>a;
	std::cout<<square(a);
} 

二、引用变量

引用变量是另一个变量的别名,如果引用变量b是引用变量a的别名,那么对b进行的操作和对a进行的操作是等价的!

1--定义方法

如果要定义int类型变量a的引用变量b,可以如下操作:

int a=10;
int &b=a;

这和指向a的指针c的定义方法有相似之处

int *c=&a;//指向a的指针c

不过,我们称变量b的类型为指向int型变量的引用

2--引用变量必须初始化!

引用不能先声明再赋值,只能进行初始化,下面的写法是错误的:

int &b; //totally_wrong
b=a  //totally_wrong

3--引用变量的忠诚性!

引用变量会和被指的那一个变量紧密联系在一起,不能在初始化引用变量后将改变其指向!

你可以将引用变量理解为一个指针常量,指向固定地址!

这就意味着,如下所示,变量b和(*pc)几乎是一模一样的!

int a;
int &b=a;
int* const pc=&a;

这里有必要插一句,我所定义的pc是一个指针常量而不是一个指向常量的指针。两者的区分方法是,从定义的等号从右往左看,如果先读到const,说明这个变量的本质属性是一个常量,然后才是个指针,也就是这个变量是指针常量;从定义的等号从右往座左看,如果先读到*,说明这个变量本质属性是一个指针,然后通过const限定不能通过指针修改指向所指向的值!

4--下面一段程序验证引用变量的性质

#include <iostream>
using namespace std;

int main(void)
{
	int* num;
	num=new int;
	*num=1;
	int &tnum=*num;
	num=new int;
    *num=2;
    cout<<tnum;
}

//结果是1,而不是2

这说明两点重要信息:

首先,指针取地址符也可以对引用变量初始化,这相当于先分配变量空间再命名,很有意思!还有,初始化以后引用变量就认准了一块地址,不会再改变,即使用于初始化这个引用变量的指针已经变换指向!

那如果这个引用变量认准的空间被释放了会怎么样呢?

#include <iostream>
using namespace std;

int main(void)
{
	int* num;
	num=new int;
	*num=1;
	int &tnum=*num;
	delete num;
	cout<<tnum;
}

读者可以自行尝试发现,这样写的话,输出的结果就是未定义的了!

三、引用变量作为函数参数

1--

如果以普通变量作为函数参数,函数在运行时事实上没有访问这些普通变量,而是创建临时变量,将普通变量的值传递给临时变量,然后对临时变量进行访问。所以如下编写的交换函数是无效的!

#include <iostream>
using namespace std;
void swap(int a,int b)
{
	int tmp=b;
	b=a;
	a=tmp;
}

int main(void)
{
	int m=1,n=2;
	swap(m,n);
	cout<<"m="<<m<<endl;
	cout<<"n="<<n;
}

可以采用指针的方法避免这一情况的出现,但C++还可以用引用!把引用变量作为参数,就可以解决这一问题

#include <iostream>
using namespace std;
void swap(int &a,int &b)
{
	int tmp=b;
	b=a;
	a=tmp;
}

int main(void)
{
	int m=1,n=2;
	swap(m,n);
	cout<<"m="<<m<<endl;
	cout<<"n="<<n;
}

(结果是m=2,n=1)

注意,没有创建引用变量,但问题就这样解决了!它的解决方法是让a和b作为m和n的别名!(有趣的是,这并不意味着a和b这两个函数参数不可以与m和n重名,说明函数变量的独立性还是有的!)

2--

如下代码中出现了函数引用参数和实参类型并不匹配的情况,这时候编译器会创建临时变量来解决问题

#include <iostream>
using namespace std;
void swap(double &m,double &n)
{
	double tmp=n;
	n=m;
	m=tmp;
}

int main(void)
{
	int m=1,n=2;
	swap(m,n);
	cout<<"m="<<m<<endl;
	cout<<"n="<<n;
}

按照C++ primer plus的说法,这时候编译器会创建临时变量,来替换m和n,这样swap函数的功能就不能实现了;然后,笔者尝试后,发现是可以实现的。。。。。。

只能说,这样的写法是不严谨的,最好别这么做,而且在现代的编译器中,这种做法无法通过编译!

3--const限定符

函数声明时加上const限定符号可以禁止通过引用来改变实参的值!

#include <iostream>
using namespace std;
void print(const int &m,const int &n)
{
	cout<<m<<" "<<n;
}

int main(void)
{
	int a=1,b=2;
	print(a,b);
}

这时,如果在函数定义中加上m=3这样的赋值语句,是无法通过编译的!

四、引用变量作为返回值

1--

想不到吧,引用变量可以作为函数的返回值,返回指向某个类型某个变量的引用。以下是程序示例:

#include <iostream>
using namespace std;

int& myplus(int &a,int &b);
int main(void)
{
	int m=1,n=10,p=100;
	cout<<myplus(p,myplus(m,n));
}

int& myplus(int &a,int &b)
{
	a=a+b;
	return a;
} 

myplus(m,n)函数返回了一个指向m的引用,它就可以被当作m使用!

2--注意,返回的引用的对于的内存空间必须存在,否则会出问题!

3--同样也可以在函数定义前加上const限定符,返回的引用就不可以作为左值被修改了!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值