社区
C++ 语言
帖子详情
====MVP级强滢请进 请帮忙用ET技术实现一个极其小的矩阵类,内有要求,不是很难,对我很难,感谢先
mynetpc
2004-11-21 01:47:15
要求用模板类型。要求实现[i][j],要求用ET方法实现+ 。 要求内存不泄漏
...全文
168
13
打赏
收藏
====MVP级强滢请进 请帮忙用ET技术实现一个极其小的矩阵类,内有要求,不是很难,对我很难,感谢先
要求用模板类型。要求实现[i][j],要求用ET方法实现+ 。 要求内存不泄漏
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
13 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
mynetpc
2004-11-26
打赏
举报
回复
顶
yuanye2008
2004-11-26
打赏
举报
回复
满天都是小星星!
sandrowjw
2004-11-26
打赏
举报
回复
偶4来学习的,devcpp的库里面好像有valarray(矢量运算)的et实现,不过真的很麻烦:(
mynetpc
2004-11-25
打赏
举报
回复
就实数范围吧,不用考虑复数域了
mynetpc
2004-11-25
打赏
举报
回复
看来俺的问题够档次啊。 呵呵
哪位能给一短示例啊,比如用ET实现[i][j]和*
zhangfjj
2004-11-22
打赏
举报
回复
呵呵,五星级的强淫来了!
:)
蒋晟
2004-11-22
打赏
举报
回复
这个矩阵类库怎么看怎么像偶大二的作业……实数还简单,不知道ET怎么考虑虚数矩阵的……
xuzheng318
2004-11-22
打赏
举报
回复
哇,都是星星,照的我眼睛睁不开了
yjh1982
2004-11-22
打赏
举报
回复
要求内存不泄漏
.......................
搞笑了点吧....
goodluckyxl
2004-11-22
打赏
举报
回复
偶是来看看MVP及人物的回答的
顺便来学习...
Andy84920
2004-11-21
打赏
举报
回复
转自:http://www.allaboutprogram.com/content/view/26/31/
简单介绍一下 Expression Template
属于作者: elminster
在 C++ 那几种渐渐为人们所熟悉的“奇技淫巧”之中,ET 可能是最具实用价值的技术之一了。借着它的帮助,人们可以构造出兼具便利和高效的通用库来。那么 ET 究竟是什么呢?笼统地说,ET 就是利用类型信息来储存表达式结构的技术。按照这个说法,人们通常所说的 lambda 表达式也可以划入 ET 技术的范畴,不过这里我主要以 ET 在矩阵运算方面的应用为例,lambda 表达式我会另文加以介绍。
这篇文章我来介绍一下 Express Template(以下简称 ET)。
在 C++ 那几种渐渐为人们所熟悉的“奇技淫巧”之中,ET 可能是最具实用价值的技术之一了。借着它的帮助,人们可以构造出兼具便利和高效的通用库来。那么 ET 究竟是什么呢?笼统地说,ET 就是利用类型信息来储存表达式结构的技术。按照这个说法,人们通常所说的 lambda 表达式也可以划入 ET 技术的范畴,不过这里我主要以 ET 在矩阵运算方面的应用为例,lambda 表达式我会另文加以介绍。
一、动机
按照常规,当我们学习线性代数的时候,矩阵运算是用代数式子给出的。因此,很自然的,当我们在计算机上编写程序的时候,我们希望所使用的矩阵库可以支持代数化的语法(为了便于讨论,假设 m1、m2、m3、m4 是四个 N 维的整数方阵,下同):
== <code1> ================================
matrix m1, m2, m3, m4;
... ...
// 我们希望这样
m1 = m2 + m3 * m4;
// 而不是这样
mul(m1, m3, m4);
add(m1, m1, m2);
== </code1> ===============================
对于 C++ 来说,要实现一个库支持这样的语法非常简单,我们只要书写一个类 matrix 并为之重载相应的运算符就行了,像这样:
== <code2> ================================
class matrix
{
// ... ...
int content[N][N];
public:
int get_value(int i, int j) const { return content[i][j]; }
const matrix& operator=(const matrix& other)
{
if( this == &other )
return *this;
for(int i=0; i<N; ++i)
for(int j=0; j<N; ++j)
content[i][j] = other.content[i][j];
}
friend matrix operator+(const matrix& lhs, const matrix& rhs)
{
matrix tmp;
for(int i=0; i<N; ++i)
for(int j=0; j<N; ++j)
tmp.content[i][j] = lhs.content[i][j] + rhs.content[i][j];
}
// ... ... 乘法类似实现,不赘
};
== </code2> ===============================
经过一番小小的努力,我们就能够使用像 code1 那样的语法了。然而这样的实现方式,对于学习 C++ 语言的朋友来说或许是一个不错的练习,但若要将之投入实用,却是让人根本无法接受的。运算符重载只是语法糖,漂亮的语法下面,其实质是嵌套的函数调用,稍加分析就可以发现,上述实现方式在支持代数化的语法的同时,在效率方面付出了巨大代价。以 code1 中的表达式为例:
== <code3> ================================
// 这个表达式
m1 = m2 + m3 * m4;
// 实质是
m1.opeartor=( operator+( m2, opeartor*(m3, m4) ) );
== </code3> ===============================
结合上面的代码,我们可以看到当调用 operator* 计算 m3*m4 的时候,我们先构造了一个矩阵 tmp ,然后执行乘法运算计算其内容,接着当函数返回时,tmp 析构,而返回值是一个临时对象,它必须从 tmp 拷贝构造并在恰当的时刻析构。在这个过程中,除了实际所需运算外,我们得多做一次构造,一次拷贝构造和两次析构 —— 光是一次拷贝构造,就意味着要把 N^2 个数挨个复制一遍,其他运算符差不多也是如此。可以预见,我们使用的表达式越长、越复杂,这些开销就越大,最终可能导致程序的执行效率下降一个数量级。
这显然是无法令人接受的,因此,长久以来人们依然只能使用 add/mul 这样怎么看都像汇编指令的语法,Fortran 也依然大行其道。但借着 ET 的帮助,事情就不同了:我们仍然可以写 m1 = m2 + m3 * m4; ,同时又不损及效率。
这当然很 cool,可它是怎么干的呢?
二、技术
从前面的分析可以知道,我们的时间其实主要都浪费在构造、保存和复制中间结果上了,要提高效率,必须设法消除这些中间结果。对此,ET 的答案是:将整个表达式的结构编码入类型信息,借此将实际计算延迟到实际需要之时,也就是执行赋值操作的时候。唔,这么说实在太笼统,还是让我们来看看代码,看看它是怎么做的:
== <code4> ================================
// matrix 实现
class matrix
{
// ... ...
int content[N][N];
public:
int get_value(int i, int j) const { return content[i][j]; }
template<class E>
const matrix& operator=(const E& expr)
{
for(int i=0; i<N; ++i)
for(int j=0; j<N; ++j)
content[i][j] = expr.get_value(i, j);
return *this;
}
};
== </code4> ===============================
首先是 matrix 。这里 matrix::operator= 变成了一个模板函数,而且我调整了参数的命名,指明传入的参数 expr 是一个表达式,它的类型是模板参数 E。这里使用模板是必要的,因为 expr 这个表达式的结构信息保存在它的类型之内,不同的表达式就有不同的类型 —— 但所有的表达式都可以通过 get_value(i, j) 来获得这个表达式运算结果中的各个元素。接下来的问题就是怎样把表达式的结构放进类型信息了。简单起见,这里只展示加法的具体实现:
== <code5> ================================
// 加法实现
template<class L, class R>
class expr_add
{
const L& lhs;
const R& rhs;
public:
expr_add(const L& l, const R& r) : lhs(l), rhs(r) {}
int get_value(int i, int j) const
{
return lhs.get_value(i, j) + rhs.get_value(i, j);
}
};
template<class L, class R> inline
expr_add<L, R> operator+(const L& lhs, const R& rhs)
{
return expr_add<L, R>(lhs, rhs);
}
== </code5> ===============================
上面这种手法是 ET 区别于其他技术的地方。在这里,operator+ 这个重载的运算符并不实际完成加法操作,而是返回一个保存了表达式有关信息的对象,expr_add 。expr_add 这个类模板代表加法表达式,它的模板参数 L 和 R 分别代表了这个加法表达式左子表达式和右子表达式的类型,并使用两个引用成员 lhs 和 rhs 分别保存实际的左右子表达式。现在让我们来看看当我们在程序写下 m1 = m2 + m3 + m4 + m5; 的时候会发生什么:
== <code6> ================================
// 按照运算符重载的规则:
m1 = m2 + m3 + m4 + m5;
// 等价于:
m1.operator=( operator+( operator+( operator+(m2, m3), m4 ), m5 );
// 让我们把等号右边的这一串函数嵌套调用展开,看看各级的返回类型是什么
// (matrix 简写为 M)
m1.operator=( operator+( operator+( operator+(m2, m3), m4 ), m5 );
// ~~~~~~~~~~~
// expr_add<M, M>
// ~~~~~~~~~~~~~~~~~~~~~~
// expr_add< expr_add<M, M>, M>
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// expr_add< expr_add< expr_add<M, M>, M>, M>
== </code6> ===============================
可以看到,expr_add 的两个模板参数就像二叉树一样将整个表达式的结构递归地保存在类型信息之内,等到我们在 operator= 里面取 expr.get_value(i, j); 的时候,由于这一函数的 inline 性质,这个调用可以其逐级展开:
== <code7> ================================
// 下面这个调用:
content[i][j] = expr.get_value(i, j);
// 我们可以这样展开:
// expr_add< expr_add< expr_add<M, M>, M >, M >::get_value
// 展开为:
// expr_add< expr_add<M, M>, M >::get_value + M::get_value
// 展开为:
// expr_add<M, M>::get_value + M::get_value + M::get_value
// 展开为:
// M::get_value + M::get_value + M::get_value + M::get_value
// 因此,最终我们可以得到
content[i][j] = m2.get_value(i, j) + m3.get_value(i,j) + m4.get_value(i, j) + m5.get_value(i,j);
还未帖完,放不下.所以请看原址.
Andy84920
2004-11-21
打赏
举报
回复
但是如果你需要我把所有的都完整的写出来,....咦....不是偶滴作业啊.^_^
等有时间再看看.
Andy84920
2004-11-21
打赏
举报
回复
这个不需要MVP级人物写.
MVP
带你零基础学习Access数据库
1、金牌讲师:王宇虹-Office中国超
级
讲师 ØOffice交流网站长 Ø2004-2019连续14年微软最有价值专家(
MVP
) Ø近15年Office/Access企业开发经验 与ERP实施经验 Ø十多年企业管理软件开发和管理咨询经验,...
Android电商
MVP
框架
为什么使用
MVP
, ...最主要的原因是:使用
MVP
框架即使是项目开发一般让另
一个
人
进
行开发也可以很好的入手,而不会出现MVC那种Activity分工不明确,
一个
类
中调用几百个方法作者自己都
难
以搞清的情况。 ...
一文速读阿里云
ET
大脑 ——阿里云机器智能首席科学家闵万里详解数字驱动的智能之路...
本篇文章为闵万里现场发言的整理,
内有
大量
技术
干货,不容错过。 智能从哪里来?人的智慧来自大脑,产业的智慧来自于
ET
大脑。
ET
大脑很简单,就是挖掘数据新能源的价值。数据能源和传统能源有本质的...
三分钟让你深入了解//MVC、
MVP
、MVVM模式(深度解析、全实例讲解)
在Android开发中,当你梳理完需求后,你要做的并不是马上写下你的第一行代码,而是需
先
设计好整个项目的
技术
框架 今天,我将全面介绍Android开发中主流的
技术
框架MVC、
MVP
与MVVM模式,并实例讲解
MVP
模式,希望您们...
Android App的设计架构:MVC,
MVP
,MVVM与架构经验谈
转载:https://www.tianmaying.com/tutorial/AndroidMVC和MVC框架模式一样,Model模型处理数据...MVC,
MVP
等架构讲的是什么?区别是什么?本文就来带你分析一下这几个架构的特性,优缺点,以及App架构设计中应该注...
C++ 语言
64,639
社区成员
250,578
社区内容
发帖
与我相关
我的任务
C++ 语言
C++ 语言相关问题讨论,技术干货分享,前沿动态等
复制链接
扫一扫
分享
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++
技术论坛(原bbs)
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
请不要发布与C++技术无关的贴子
请不要发布与技术无关的招聘、广告的帖子
请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下
试试用AI创作助手写篇文章吧
+ 用AI写文章