inline-内联函数的使用
使用方式
- 在函数声明前加上inline
- 在函数定义前加上inline
inline double square(double x){return x*x;}//函数定义前
#include<iostream>
using namespace std;
inline double square(double x);
int main()
{
cout<<square(16)<<endl;
return 0;
}
double square(double x){return x*x;}//函数声明前
内联与宏
宏事实上是一种文本替换的方式,比如
#define square(X) X*X
#include<iostream>
using namespace std;
int main()
{
int c=5;
cout<<square(4.5)<<'\t'<<"4.5*4.5"<<endl;
cout<<square(4.5+7.5)<<'\t'<<"4.5+7.5*4.5+7.5"<<endl;
cout<<square(c++)<<'\t'<<"c++*c++"<<endl;
return 0;
}
//结果是20.25 45.75 30
可以看到其实就是用数字或者表达式代替了X的位置,需要指出尽量避免这样使用,使用内联函数会更好
引用变量
1.创建引用变量
int& rodents=rats;
注意:
- 可以确认的是这两个变量指向相同的地址
- &在这里并不是取址运算符
- 引用变量必须在声明时就进行初始化不能出现
int & rodents; - 引用变量一旦与某个变量关联起来就一直效忠于它
//如下代码无法改变rodent引用的还是rats这一事实
int rats=101;
int *pt=&rats;
int &rodents=*pt;
int bunny=50;
pt=&bunny;
2.使用引用(左值)作为函数参数
2.1.简单使用
//考虑一下两个交换函数
void swap(int &a,int &b);
void swap(int a, int b);
很简单,前者能交换原函数的两个参数,而后者不行
2.2.需注意事项
引用变量传递参数只能是传递变量,无法传递表达式以及常量
swap(a+3,b+6);
2.3.应尽可能使用const
可优化方案:引入关键字const 可以产生临时变量储存传入的值从而不会出现无法执行的情况,同时如果引用对象的值发生改变,系统无法编译
#include<iostream>
using namespace std;
double cube(const &ra){return ra*ra*ra;}
int main()
{
double side=3.;
double *pd=&side;
double & rd=side;
long edge=5L;
double lens[4]={2.0,3.0,5.0,6.0};
double c1= cube(side);
double c2= cube(lens[2]);
double c3= cube(rd);
double c4= cube(*pd);
double c5= cube(edge);
double c6= cube(7.0);
double c7= cube(side+10.0);
return 0;
}
以上都是可以执行的,尽管是edge以及7.0和side+10.0系统将创建一个临时变量储存他们,并进行引用
2.4.右值引用
double && rref=std::sqrt(36.00);//正确
double & rref=sqrt(36.00);//错误
2.5.将引用用于结构
2.5.1 返回引用
? 当返回值为引用的时候,效率更高,因为普通的return事实上创建了一个中间变量,进行了两次复制才完成相同的操作
#include<iostream>
using namespace std;
#include<string>
struct people{string name;int age;int sex;double money;};
void add_money(people & one)
{
cout<<"great congratulations to you!"<<endl;
one.money+=10000;
}
void show_state(const people & one)
{
cout<<"now,you:"<<endl;
cout<<one.name<<endl;
cout<<one.age<<endl;
cout<<one.sex<<endl;
cout<<one.money<<endl;
}
people & trade(people & one)//返回一个结构的引用
{
one.age+=10;
one.money*=2;
return one;
}
int main()
{
people one={"xiaoming",18,0,0.1};
cout<<"the first condition:"<<endl;
show_state(one);
add_money(one);
show_state(one);
cout<<"a devil trade with you"<<endl;
show_state(trade(one));//show_state的传入参数是one的引用所以one展示的是one的引用的引用,还是与one一个地址
return 0;
}
注意:
- 返回函数时避免返回临时创建的变量的引用,因为这种变量往往在函数结束调用就被系统清除内存
//比如下面这段代码
const people & cloze(people & one)
{
people two;
two=one;
return two;//Big error.two马上就会被清除内存,于是其引用即将无效
}
函数模板
简要介绍
函数模板可以函数有同时对不同的数据类型进行操作,使用该方法,你可以给函数的参数列表放入各种类型的实参
#include<iostream>
using namespace std;
template <typename Anytype>//"只能"创建一次,Anytype只是一个可以任意取名的名字
void Swap(Anytype &a,Anytype &b)
{
Anytype temp;
temp=a;
a=b;
b=temp;
}
//但是在作用完后可以再创建一次template <typename Anytype>,比如这里
int main()
{
double x=100;double y=10.323242;
Swap(x,y);//替换两个浮点数的值
cout<<x<<'\t'<<y<<endl;
int a=23,b=19;
Swap(a,b);//替换两个整数
cout<<a<<'\t'<<b;
return 0;
}
注意
typename 可以是class ,而且都不要加分号
template <typename T> /*is the same as*/
template <class T>
-
该方法只是使函数定义更简单,并没有使复杂度降低。 -
模板虽然具有通用性,但是并不是所有的类型都会满足某一特定的运算符
//比如赋值运算符
template <class T>
void f(T a,T b)
{
a=b//may be an error.比如T是数组类型,因为数组没有赋值这一说法
}
- 如果现在已经有了一个非模板函数与一个同名同类型的模板函数,优先调用非模板函数
#include <iostream>
using namespace std;
template <class T>
T fun(T a,T b)
{
return a+b;
}
int fun(int a,int b)
{
return a+2*b;
}
int main()
{
int m=78,n=89;
cout<<fun(m,n)<<endl;
return 0;
}
//编译后结果输出256,可以看出优先采用了第二种定义方式
拓展
- 混合使用任意定义参数
#include <iostream>
using namespace std;
template <class T,class A>//一个实例
void add(T a,A b)
{
decltype(a) res=a+b;//你可以这样理解,把a的类型赋给res,甚至可以人为这是一种初始化的操作
cout<<res<<endl;
}
int main()
{
int LIM=520;
double MIL=1314000.0;
add(LIM,MIL);
return 0;
}
- decltype的拓展
但是一旦考虑return这样一个函数,我们并不知道应该返回何种类型
?type? add(T a,A b)
{
return a+b;
}
解决方案:
通式:auto function (typename para1,...) ->type(可以是double,也可以是decltype(parament))
#include <iostream>
using namespace std;
template <class T,class A>
auto add(T a,A b) ->decltype(a)//使输出结果为a的类型
{
return a+b;
}
int main()
{
int LIM=520;
double MIL=1314000.0;
cout<<add(LIM,MIL);
return 0;
}
|