gxqcn
发表于 2010-8-5 12:04:28
HugeCalc 的 C++ 接口中产生的临时变量管理机制是由 C++ 标准负责的,HugeCalc 并没有特别维护。(C 接口则有特别维护)
比如说,“c=a+b”,其实它调用了两个运算符:+、=
前者产生一个临时变量,然后赋值给显示变量,而后就可销毁了。
具体是否如此作为,得看C++机制了。
“(a+b)*(a+b) ”中共产生3个临时变量,但有两个是(a+b)产生的,它们是不同的临时对象,内存地址不会相同。
forcal
发表于 2010-8-5 12:33:05
我查到一个说明:C++运算符重载函数为值返回的时候会产生临时变量,临时变量与局部变量result的复制会调用拷贝构造函数,临时变量的生命周期是在拷贝构造函数运行完成后才结束。
这样说来,c=a+b,这是可以正常运行而没有内存泄露的,a+b产生了临时变量,直到赋值给c后该临时变量的生命期才结束。
但c=(a+b)*(a+b) ,产生的3个临时变量,只有最后一个赋值给c后可以正常销毁,而(a+b)产生的两个临时变量由于没有赋值,是不是没有销毁而存在内存泄露呢?
有点题外话了,但这个不是很懂,还是请教一下?
gxqcn
发表于 2010-8-5 13:09:32
(a+b) 应该是在调用乘法运算符后自动销毁的。
forcal
发表于 2010-8-5 15:26:11
(a+b) 应该是在调用乘法运算符后自动销毁的。
gxqcn 发表于 2010-8-5 13:09 http://bbs.emath.ac.cn/images/common/back.gif
恩,是这样的。
C++ 临时变量应该在导致临时变量创建的"完整表达式"求值过程的最后一个步骤被析构。
这样,脚本还得依靠自己管理临时变量。
forcal
发表于 2010-8-5 17:06:18
在Forcal脚本中将通过函数和运算符两种方式实现HugeCalc 的大数运算功能。
以加法为例,函数Add(a,b,c)将实现a=b+c,或者在函数oo中直接使用b+c。
对没有提供运算符的运算,用函数实现,如乘方,一般格式Pow(a,b,c)将实现a=b^c,在函数oo中可使用函数Pow(b,c),不过Pow(b,c)将返回一个临时对象。
在函数oo中使用运算符或函数,表达式将非常简洁,容易理解,但由于存在很多临时变量的生成和销毁,故效率较低。
个人感觉,C++提供了运算符重载,主要是为了用户的方便,效率将<=函数实现,故建议HugeCalc 在最新版本中增加与运算符重载等效的函数实现形式,所有函数的对象参数都用指针形式。一点个人意见,呵呵。
无心人
发表于 2010-8-6 08:05:44
运算符重载包括函数实现很难做到复杂的数学式的高效对象管理
需要有个好的方式管理内存
如果长度固定,可以采取不销毁的内存池方式
如果长度不固定,则不太好处理
考虑某些运算中,长度是线性增加的
也许有个不太好的方式不销毁内存而高效分配吧
说白了是自己实现局部垃圾回收
mathe
发表于 2010-8-6 09:15:51
这种优化应该在编译器内部做(既然Forcal作为一种语言)
forcal
发表于 2010-8-6 10:25:14
26# 无心人
恩,Forcal将自己实现局部垃圾回收,采用不销毁内存而高效分配方式。
forcal
发表于 2010-8-6 10:34:53
这种优化应该在编译器内部做(既然Forcal作为一种语言)
mathe 发表于 2010-8-6 09:15 http://bbs.emath.ac.cn/images/common/back.gif
Forcal是这样做的:外部模块(如Forcal扩展库)函数通知Forcal核心库哪些是临时变量,核心库通知外部模块哪些临时变量的生命期已结束,需要销毁。是否真正销毁临时变量由外部模块说了算。
计划在封装HugeCalc的扩展库中设置一个缓冲区,专门存放临时变量,一般并不真正销毁它,这样可提高效率。
forcal
发表于 2010-8-6 20:22:10
FcHugeCalc重新进行了更新,仍然使用1#的下载地址(需重新下载OpenFC)。
虽然函数并没有增加很多,但程序框架已较为完整,以后剩下的基本是体力活了。
函数名已更新,最新的说明如下:
=====================================
Forcal扩展库之FcHugeCalc:郭先强超大整数完全精度快速算法库
=====================================
用法:
1、下载OpenFC,无需安装,仅需按readme设置好。
2、复制FcHugeCalc32W.dll和HugeCalc.dll两个文件到文件夹“OpenFC\dll”。
3、打开工作区文件“OpenFC.ini”,在#LOAD{... ...}中添加如下行:
"dll\FcHugeCalc32W.dll" //郭先强超大整数完全精度快速算法库
4、执行“设置->重载动态库扩展”。
5、可能需要注册后才能正常使用,参考“HugeCalc.chm”。
=====================================
当前可用的函数:
1、HugeCalc::SetHCMax(20000):设置最多可用的HugeCalc对象,默认最多10000个HugeCalc对象
2、HugeCalc::DelAllHC():销毁所有的HugeCalc对象
3、HugeCalc::NowHCNum(100):查看当前存在,尚未销毁的HugeCalc对象,最多显示100个对象
4、HugeCalc::NewHC(HugeCalc::HI)、HugeCalc::NewHC(HugeCalc::HIX)、HugeCalc::NewHC(HugeCalc::VUI32):申请HugeInt对象、申请HugeIntX对象、申请VECTOR_UINT32对象
5、HugeCalc::DelHC(p):销毁HugeCalc对象p,p是由函数newhc返回的对象指针
6、HugeCalc::SetStr(p,"123"):给HugeCalc对象p赋值为123
HugeCalc::SetNum(p,123):给HugeCalc对象p赋值为123
HugeCalc::Set(p,q):给HugeCalc对象p赋值为q,q也是HugeCalc对象
7、HugeCalc::Show(p):输出HugeCalc对象p的内容
8、HugeCalc::Add(a,b,c):计算a=b+c,在函数oo可直接用运算符计算b+c,返回一个临时对象
9、HugeCalc::Sub(a,b,c):计算a=b-c,在函数oo可直接用运算符计算b-c,返回一个临时对象
10、HugeCalc::Mul(a,b,c):计算a=b*c,在函数oo可直接用运算符计算b*c,返回一个临时对象
11、HugeCalc::Div(a,b,c):计算a=b/c,在函数oo可直接用运算符计算b/c,返回一个临时对象
12、HugeCalc::Mod(a,b,c):计算a=b%c,在函数oo可直接用运算符计算b%c,返回一个临时对象
13、HugeCalc::Pow(a,b,c):计算a=b^c,a、b为HugeCalc对象,c为整数;在函数oo中可使用Pow(b,c),返回一个临时对象
14、HugeCalc::Fac(a,100):计算a=100!
15、HugeCalc::NextPrime(a,b):计算a=比b大的最小的素数
16、HugeCalc::GT(a,b):关系运算a>b,在函数oo可直接使用此关系运算符,返回逻辑值
17、HugeCalc::GE(a,b):关系运算a>=b,在函数oo可直接使用此关系运算符,返回逻辑值
18、HugeCalc::LT(a,b):关系运算a<b,在函数oo可直接使用此关系运算符,返回逻辑值
19、HugeCalc::LE(a,b):关系运算a<=b,在函数oo可直接使用此关系运算符,返回逻辑值
20、HugeCalc::EQ(a,b):关系运算a==b,在函数oo可直接使用此关系运算符,返回逻辑值
21、HugeCalc::NE(a,b):关系运算a!=b,在函数oo可直接使用此关系运算符,返回逻辑值
=====================================
例子1:SetTalk; //关闭计算结果及运行错误输出,并不阻止函数的输出
!using["HugeCalc"]; //使用命名空间HugeCalc,可简化函数的使用
mvar: //使用隐含模块变量声明方式
i: printff["\r\n"], //输出一个换行符
a=NewHC.SetStr["1111111111111111111111111111111"].free[], //申请HugeInt对象并赋值,自动销毁该对象
b=NewHC.SetStr["11111111112222222222222"].free[], //申请HugeInt对象并赋值,自动销毁该对象
c=NewHC.Add.Show[].free[], //申请HugeInt对象c,计算c=a+b并输出结果,自动销毁该对象
printff["\r\n"], //输出一个换行符
oo{.Show[]}; //函数oo中的运算符是重载的,计算a+(b+c)+(a+b)并输出结果-------------------------------------
例子2:SetTalk;
!using["HugeCalc"];
mvar:
i: printff["\r\n"],
a=NewHC.SetStr["1111111111111111111111111111111"].free[],
b=NewHC.SetNum.free[],
oo{.Show[]};-------------------------------------
例子3:!using["HugeCalc"];
mvar:
i: oo{
printff["\r\n"],
//函数oofree[]指出由oo函数销毁该对象
a=NewHC.SetStr["1111111111111111111111111111111"].oofree[],
b=NewHC.SetStr["11111111112222222222222"].oofree[],
{d=, c=Pow(a,10), a+(d-Pow(a,50)%b)*(c+c/b)}.Show[]
};-------------------------------------
例子4:!using["HugeCalc"];
mvar:
t0=sys::clock();
i: printff["\r\n"],
a=NewHC.SetNum.free[],
b=NewHC.SetNum.free[],
c=NewHC.SetNum.free[],
aa=NewHC.free[],
i=0, a.NextPrime, aa.NextPrime,
while{LE(aa,b),
oo{
dd=, cc=Pow(aa,50),
c.Set
},
a.Set, aa.NextPrime,
i++
},
c.Show(),
i;
/1000;=====================================
forcal 2010.8.6