IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 内联函数+引用+模板 -> 正文阅读

[C++知识库]内联函数+引用+模板

inline-内联函数的使用

使用方式

  1. 在函数声明前加上inline
  2. 在函数定义前加上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;

注意:

  1. 可以确认的是这两个变量指向相同的地址
  2. &在这里并不是取址运算符
  3. 引用变量必须在声明时就进行初始化不能出现int & rodents;
  4. 引用变量一旦与某个变量关联起来就一直效忠于它
//如下代码无法改变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;
}

注意:

  1. 返回函数时避免返回临时创建的变量引用,因为这种变量往往在函数结束调用就被系统清除内存
//比如下面这段代码
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;
}

注意

  1. typename可以是class,而且都不要加分号
template <typename T> /*is the same as*/
template <class T>
    
  1. 该方法只是使函数定义更简单,并没有使复杂度降低。

  2. 模板虽然具有通用性,但是并不是所有的类型都会满足某一特定的运算符

//比如赋值运算符
template <class T>
void f(T a,T b)
{
    a=b//may be an error.比如T是数组类型,因为数组没有赋值这一说法
}
  1. 如果现在已经有了一个非模板函数与一个同名同类型的模板函数,优先调用非模板函数
#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,可以看出优先采用了第二种定义方式

拓展

  1. 混合使用任意定义参数
#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;
}
  1. 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;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:08:08  更:2022-04-01 23:10:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:38:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码