C++ template的一些高级用法(元编码,可变参数,仿函数,using使用方法,. C++ 智能指针)
1 . 通用函数可变参数模板
对于有些时候,我们无法确切的知道,函数的参数个数时,而又不想过多的使用所谓的函数重载,那么就可以效仿下面的例子:
#include<iostream>
#include<Array>
void showall() { return; } template <typename R1 ,typename... Args> void showall(R1 var, Args...args) { std::cout << var << std::endl;
showall(args...);
} int main(int argc, char * args[]) { showall(, , , , );
showall("gxjun","dadw","dasds");
showall(1.0,2.0,3.5);
std::cin.get();
return ;
}
在游戏开发中,时常会用到这样的模板,类型不确定,参数的个数不确定,所以需要用一种类似于递归的函数来处理。 第一个函数,表示的是在参数为0时,结束。
效果:
2. 如何使用仿函数:
首先仿函数的定义: ,仿函数也叫函数对象(Function Object, or Functor),定义就是任何可以像函数一样被调用的对象。一个普通的函数是函数对象,一个函数指针当然也是,广义上说任何定义了operator()的类对象都可以看作是函数对象。 (找到文档)
其实,往直白的地方说,就是一个不是函数但是具有函数功能且用法和函数相同的对象(结构体或者类)。
下面举个栗子(用结构体实现函数功能):
/*关于C++仿函数*/
#include<iostream>
#include<functional>
using namespace std;
using namespace std::placeholders; template <typename R1 , typename R2>
struct Calc
{
void add(R1 a) {
cout << a << endl;
};
void add_1(R1 a, R1 b) {
cout << a + b << endl;
}
}; int main(int argc, char * args[]) { //函数指针
void(Calc<int, double>::*fc)(int a) = &Calc<int, double >::add;
// fc(25);
//显然上面的式子比较的麻烦 Calc < int, int> calc;
auto fun = bind(&Calc<int, int >::add, &calc, _1);
auto fun_2 = bind(&Calc<int, int >::add_1, &calc, _1,_2);
fun();
fun_2(,);
cin.get();
return ;
}
对于bind()这个函数,开头的是地址,函数名,后面的是第一个列子中的Args....不定参数类型、
效果图为:
3. 使用using别名,函数指针,typdef来实现函数的调用
虽然是寥寥的几行代码,但是功能在实际应用中,却会发挥很大的作用。
//using别名使用用法
#include<iostream>
#include<windows.h>
int calc() {
//当为无参数时,返回0值
return ;
} template <typename R1 ,typename...Args>
int calc(R1 a, Args...args) { return a + calc(args...);
} int main(int argc , char * args []) { //使用函数指针
int(*fun) (int ,int ,int ,int ) = calc;
system("echo 使用函数指针实现1~4累加");
std::cout << fun(,,,)<<std::endl;
//使用typedef来实现该功能
system("echo 使用typedef实现1~4累加");
typedef int(*Add)(int, int, int);
Add Gadd = calc;
std::cout << Gadd(, , ) << std::endl;
//使用using别名来实现这么个功能
system("echo 使用using实现1~4累加");
using Func = int(*) (int, int, int, int);
Func func = calc;
std::cout << func(, , , ) << std::endl;
std::cin.get();
return ;
}
效果图:
4. C++模板元编程:
对于模板元编程: 我的理解是,你所要的计算,在编译的时候,已经处理玩了,只需要在运行的时候输出结果即可!
当我们每每学到模板元编程的时候,就会有一个混淆的词汇出现,哒,看------函数式编程。 到底什么是函数式编程呢?
建议去看这篇文章,http://www.ruanyifeng.com/blog/2012/04/functional_programming.html 模板元编程用处广泛,
我们知道当硬件条件限制的情况下,除了优化算法,还有一种途径,那就是用模板元编程。 现在就让我们来看看这个金典的应用吧!
斐波那契数列的计算......
#include<iostream>
#include<time.h>
#include<windows.h>
/*
斐波那契数列
H(1)=H(0)=1;
H(N)= H(N-1)+H(N-2);
*/
using namespace std; /* 普通版普通版 */
using _int = long ; //使用别名 _int feibona(_int ac) {
if (ac == ||ac==) return ;
return feibona(ac-) +feibona(ac-);
} /* 使用元编程 完全特化版 方法如下*/
template <_int N>
struct data {
//采用枚举
enum { res = data<N - >::res + data<N - >::res };
}; template <>
struct data<> {
//采用枚举
enum { res = 1L };
}; template <>
struct data<> {
//采用枚举
enum { res = 1L };
}; int main(int argc, char * args[]) { time_t a ,b;
a = clock(); //开始记录时间
cout << data<45L>::res << endl;
b = clock(); //开始记录时间
system("echo 采用元编程所消耗的时间");
cout << (double)(b - a) / CLK_TCK<<"ms"<<endl;
a = clock();
cout << feibona(45L) << endl;
b = clock();
system("echo 采用普通的算法所消耗的时间");
cout << (double)(b - a) / CLK_TCK << "ms" << endl;
cin.get();
return ;
}
两者相对比的效果图:
5 C++智能指针 ,关于智能指针和普通指针,的几种行为的对比
/*
智能指针:
对于C++而言: std::auto_ptr<double> ptr(new double);
对于C++11新的智能指针: std::unique_ptr<double> ps(new double);
通过下面几组数据做些一点
*/
#include<iostream>
#include<memory>
#include<windows.h>
using namespace std;
/*模式一 分配内存地址,而不手动进行回收 */
void showp() {
system("echo 分配内存地址,而不手动进行回收");
for (int i = ; i < ; i++) {
double * p = new double; //不释放
}
cin.get();
}
/* 模式二,分配地址,并手动进行回收地址 */
void showp1() {
system("echo 分配地址,并手动进行回收地址");
for (int i = ; i < ; i++) {
double * p = new double; //不释放
delete p;
}
cin.get(); }
/*模式三,分配地址,采用c++通用指针*/
void showp2() {
system("echo 分配地址,采用c++通用指针"); for (int i = ; i < ; i++) {
double * p = new double; //不释放
auto_ptr<double> ps(p); //采用智能指针,不会多释放地址,旧版本vc98支持
}
cin.get();
}
/* 模式四,分配地址,采用C++11新型指针 */ void showp3() { system("echo 分配地址,采用C++11新型指针");
for (int i = ; i < ; i++) {
auto_ptr<double> ps(new double); //采用智能指针,C++11新特性
}
cin.get();
} int main(int argc , char * args []) { //auto_ptr
//函数指针
void(*p[])() = { showp,showp1,showp2,showp3 };
//for (auto data : p) {
// data();
//}
p[]();
system("echo 按一下结束");
cin.get();
return ;
}
模式一: 消耗内存截图
模式二 吃掉的内存截图:
模式三,吃掉的内存截图:
模式四,吃掉的内存截图:
使用智能指针的好处:
1 、 不会对一个分配的地址,释放两次。如果手动释放地址,存在着重复释放或者漏放的情况。 避免内存泄露。
2. 释放及时,不会捣鼓电脑中cpu换句话说,不会吃cpu。而是电脑运缓慢....
C++ template的一些高级用法(元编码,可变参数,仿函数,using使用方法,. C++ 智能指针)的更多相关文章
- java-API中的常用类,新特性之-泛型,高级For循环,可变参数
API中的常用类 System类System类包含一些有用的类字段和方法.它不能被实例化.属性和方法都是静态的. out,标准输出,默认打印在控制台上.通过和PrintStream打印流中的方法组合构 ...
- 黑马程序员——JAVA基础之JDK1.5新特性高级for循环和可变参数
------- android培训.java培训.期待与您交流! ---------- 高级for循环 格式: for(数据类型 变量名 : 被遍历的集合(Collection)或者数组) { ...
- Go template高级用法、深入详解、手册、指南、剖析
入门示例 以下为test.html文件的内容,里面使用了一个template语法{{.}}. <!DOCTYPE html> <html> <head> <m ...
- Python彩蛋、字典、列表高级用法、元类、混入、迭代器、生成器、生成式、git
一.类与类的关系 关注公众号"轻松学编程"了解更多. is-a 继承 继承是指一个类(称为子类.子接口)继承另外一个类(称为父类.父接口)的功能, 并可以增加它自己的新功能的能力. ...
- doT的高级用法及loadData的使用
本文出自APICloud官方论坛, 感谢论坛版主 gp3098的分享. 之前直接把模板写在页面底部的script标签内的,但是现在不同. 使用了doT.js配合api的loadData方法,整个页面就 ...
- Visual Studio 宏的高级用法
因为自 Visual Studio 2012 开始,微软已经取消了对宏的支持,所以本篇文章所述内容只适用于 Visual Studio 2010 或更早期版本的 VS. 在上一篇中,我已经介绍了如何编 ...
- redis(二)高级用法
redis(二)高级用法 事务 redis的事务是一组命令的集合.事务同命令一样都是redis的最小执行单元,一个事务中的命令要么执行要么都不执行. 首先需要multi命令来开始事务,用exec命令来 ...
- SQL[连载3]sql的一些高级用法
SQL[连载3]sql的一些高级用法 SQL 高级教程 SQL SELECT TOP SQL SELECT TOP 子句 SELECT TOP 子句用于规定要返回的记录的数目. SELECT TOP ...
- 细说 ASP.NET Cache 及其高级用法
许多做过程序性能优化的人,或者关注过程程序性能的人,应该都使用过各类缓存技术. 而我今天所说的Cache是专指ASP.NET的Cache,我们可以使用HttpRuntime.Cache访问到的那个Ca ...
随机推荐
- Vcenter server 5.5上传ISO镜像
1.摘要 --- 浏览要上传的硬盘. 2.创建一个文件夹专业门存放ISO镜像. 3.选择上传文件. 4.选择文件上传即可.
- Python之路-python(面向对象一)
一.面向对象介绍 二.为什么要用面向对象开发 三.封装.继承.多态.类.方法 面向过程和面向对象的区别 编程范式: 一般情况下,拿到一个项目不同的两个人有不同的编写方式(相同的是固定的语法.数据结构) ...
- Linux安装vim失败的解决办法
最近想了解一下linux编程,于是linux系统下输入vim,发现竟然没有安装.好吧,那就安装吧.命令: sudo apt-get install vim 百度百科:apt-get是一条linux命令 ...
- 十七、Java基础---------集合框架之Map
前两篇文章中介绍了Collection框架,今天来介绍一下Map集合,并用综合事例来演示. Map<K,V> Map<K,V>:Map存储的是键值对形式的元素,它的每一个元素, ...
- 助手系列之连接mysql数据库
import MySQLdbdef main(): try: conn=MySQLdb.connect(host='127.0.0.1',user='root',passwd='pass',db='a ...
- [课程设计]Scrum 2.1 多鱼点餐系统开发进度(下单列表布局)
[课程设计]Scrum 2.1 多鱼点餐系统开发进度(下单列表布局) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅到店 ...
- iOS开发之生成二维码
一.二维码的生成 从iOS7开始集成了二维码的生成和读取功能 此前被广泛使用的zbarsdk目前不支持64位处理器 1.二维码的内容(传统的条形码只能放数字) 纯文本 名片 URL 2.生成二 ...
- Ubuntu安装R及RStudio
-------------------------------------------------------------- 自学记录,交流请发送邮件至gxz1984@gmail.com ------ ...
- USB port 如何识别不同的Charger类型
基于Qualcom 8960/8921平台 一,软件分析 1. USB charger types & Power supply types USB_INVALID_CHARGER ...
- 关于autoptr
参考自: http://www.cppblog.com/expter/archive/2009/03/29/78270.html auto_ptr是什么. 解释1.auto_ptr是一个管理指针的对象 ...