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++ 智能指针)的更多相关文章

  1. java-API中的常用类,新特性之-泛型,高级For循环,可变参数

    API中的常用类 System类System类包含一些有用的类字段和方法.它不能被实例化.属性和方法都是静态的. out,标准输出,默认打印在控制台上.通过和PrintStream打印流中的方法组合构 ...

  2. 黑马程序员——JAVA基础之JDK1.5新特性高级for循环和可变参数

    ------- android培训.java培训.期待与您交流! ---------- 高级for循环   格式: for(数据类型 变量名 : 被遍历的集合(Collection)或者数组) {   ...

  3. Go template高级用法、深入详解、手册、指南、剖析

    入门示例 以下为test.html文件的内容,里面使用了一个template语法{{.}}. <!DOCTYPE html> <html> <head> <m ...

  4. Python彩蛋、字典、列表高级用法、元类、混入、迭代器、生成器、生成式、git

    一.类与类的关系 关注公众号"轻松学编程"了解更多. is-a 继承 继承是指一个类(称为子类.子接口)继承另外一个类(称为父类.父接口)的功能, 并可以增加它自己的新功能的能力. ...

  5. doT的高级用法及loadData的使用

    本文出自APICloud官方论坛, 感谢论坛版主 gp3098的分享. 之前直接把模板写在页面底部的script标签内的,但是现在不同. 使用了doT.js配合api的loadData方法,整个页面就 ...

  6. Visual Studio 宏的高级用法

    因为自 Visual Studio 2012 开始,微软已经取消了对宏的支持,所以本篇文章所述内容只适用于 Visual Studio 2010 或更早期版本的 VS. 在上一篇中,我已经介绍了如何编 ...

  7. redis(二)高级用法

    redis(二)高级用法 事务 redis的事务是一组命令的集合.事务同命令一样都是redis的最小执行单元,一个事务中的命令要么执行要么都不执行. 首先需要multi命令来开始事务,用exec命令来 ...

  8. SQL[连载3]sql的一些高级用法

    SQL[连载3]sql的一些高级用法 SQL 高级教程 SQL SELECT TOP SQL SELECT TOP 子句 SELECT TOP 子句用于规定要返回的记录的数目. SELECT TOP ...

  9. 细说 ASP.NET Cache 及其高级用法

    许多做过程序性能优化的人,或者关注过程程序性能的人,应该都使用过各类缓存技术. 而我今天所说的Cache是专指ASP.NET的Cache,我们可以使用HttpRuntime.Cache访问到的那个Ca ...

随机推荐

  1. css3渐变色彩

    CSS3 Gradient 分为线性渐变(linear)和径向渐变(radial).由于不同的渲染引擎实现渐变的语法不同,这里我们只针对线性渐变的 W3C 标准语法来分析其用法,其余大家可以查阅相关资 ...

  2. Mac OS的phpize空信息解决办法

    Mac下执行phpize 出现以下信息 grep: /usr/include/php/main/php.h: No such file or directory grep: /usr/include/ ...

  3. W3cshool之JavaScript基础

        1.  JavaScript 对大小写敏感 名为 "myfunction"的函数和名为 "myFunction" 的函数是两个不同的函数,同样,变量 & ...

  4. The type XXX cannot be resolved. It is indirectly referenced from required .class files错误.....

    遇到The type XXX cannot be resolved. It is indirectly referenced from required .class files错误.....,查找的 ...

  5. Java语言的特点

    一. 面向对象:其实是现实世界模型的自然延伸.现实世界中任何实体都可以看作是对象.对象之间通过消息相互作用.另外,现实世界中任何实体都可归属于某类事物,任何对象都是某一类事物的实例.如果说传统的过程式 ...

  6. JVM常见配置汇总

    堆设置 -Xms:初始堆大小 -Xmx:最大堆大小 -XX:NewSize=n:设置年轻代大小 -XX:NewRatio=n:设置年轻代和年老代的比值.如:为3,表示年轻代与年老代比值为1:3,年轻代 ...

  7. 曲线提取数据Engauge Digitizer

    可导出CSV格式数据 其它参考: http://blog.sina.com.cn/s/blog_4ae65b4d0100z8cg.html 其它曲线提取数据的软件还有: GetData.Windig ...

  8. [转] 停止支持的老版本ubuntu源列表-old-releases

    我使用的是ubuntu 9.10,在网上找了大半个月之后,今天终于找到了可用的源地址.感谢这位cgjcgs仁兄. 点击阅读原文 ubuntu的普通版本支持的时间都有限,过了支持的时间,更新源都会被停用 ...

  9. SQL SERVER 2008 登陆失败(SQL和windows都没有对应的权限)

    转自:http://www.cnblogs.com/zerocc/p/3425431.html 昨天在测试一些权限今天早上来就发现SQL SERVER 登陆不上去,报错为: 用户登陆失败:消息 184 ...

  10. windows+caffe(三)——求取图片的均值

    这个要在图片已经转化成lmdb格式下才能求均值... 1.查看caffe根目录下的bin是否存在compute_image_mean.exe(用的happey大神的) 如果没有存在,你需要打开Main ...