客服咨询
备案专员
域名专员
问题提交
汇款方式
帮助首页
常见问题
视频问题
新闻公告
最新资讯
备案专题
会员管理
主站导航
首页
域名注册
虚拟主机
云主机
VPS主机
智能建站
建站服务
微信平台
企业邮箱
管理中心
欢迎来到万象互联帮助中心,我们将竭力为您解决问题!
域名问题
主机问题
邮局问题
建站问题
财务问题
汇款方式
关于我们
业务流程
会员注册
域名注册
虚拟主机
企业邮局
数据库
VPS主机
代理平台
智能建站
其他视频
公告列表
新闻信息
网站推广
网站制作
Net教程
PHP教程
JSP教程
数据库
其他信息
公告栏
法律法规
系统帮助
相关下载
政务公开
备案常见问题
登录www.163ns.com会员管理中心
您现在的位置:
万象互联帮助中心
>>
最新资讯
>>
详细内容
<<返回上一页
浅谈Ruby语言中的String
大
中
小
文章来源:
万象互联
更新时间:
2012-11-19
分享到:
Ruby语言中的String是mutable的,不像java、C#中的String是immutable的。比如
代码如下:
str1="abc"
str2="abc"
在java中,对于字面量的字符串,jvm内部维持一张表,因此如果在java中,str1和str2是同一个String对象。而在Ruby中, str1和str2是完全不同的对象。同样,在java中对于String对象的操作都将产生一个新的对象,而Ruby则是操纵同一个对象,比如:
代码如下:
str="abc"
str.concat("cdf")
此时str就是"abccdf"。Ruby对String是怎么处理的呢?我们只谈谈c ruby中的实现,有兴趣的先看看这篇文章《管窥Ruby——对象基础》。在ruby.h中我们可以看到String对象的结构,Ruby中的对象(包括类也是对象)都是一个一个的struct,String也不能例外:
代码如下:
struct RString {
struct RBasic basic;
long len;
char *ptr;
union {
long capa;
VALUE shared;
} aux;
};
//ruby.h
显然,len是String的长度;ptr是一个char类型的指针,指向实际的字符串;然后是一个联合,这个稍后再说。如果你看看ruby.h可以发 现,几乎所有定义的对象结构都有一个struct RBasic。显然,struct RBasic包含由所有对象结构体共享的一些重要信息的。看看RBasic:
代码如下:
struct RBasic {
unsigned long flags;
VALUE klass;
};
其中的flags是一个多用途的标记,大多数情况下用于记录结构体的类型,ruby.h中预定义了一些列的宏,比如T_STRING(表示struct RString),T_ARRAY(表示struct RArray)等。Klass是一个VALUE类型,VALUE也是unsigned long,可以地将它当成指针(一个指针4字节,绰绰有余了),它指向的是一个Ruby对象,这里以后再深入。
那么联合aux中的capa和shared是干什么用的呢?因为Ruby的String是可变的,可变意味着len可以改变,我们需要每次都根据len的 变换来增减内存(使用c中的realloc()函数),这显然是一个很大的开销,解决办法就是预留一定的空间,ptr指向的内存大小略大于len,这样就 不需要频繁调用realloc了,aux.capa就是一个长度,包含额外的内存大小。那么aux.shared是干什么的呢?这是一个VALUE类型, 说明它是指向某个对象。aux.shared其实是用于加快字符串的创建速度,在一个循环中:
ruby 代码
whiletruedo重复 a="str"#以“str”为内容创建字符串,赋值给a a.concat("ing")#为a所指向的对象添加“ing” p(a)#显示“string” end
每次都重新创建一个"str"对象,内部就是重复创建一个char[],这是相当奢侈,aux.shared就是用于共享char[],以字面量创建的字符串会共享一个char[],当要发生变化时,将字符串复制到一个非共享的内存中,变化针对这个新拷贝进行,这就是所谓的“copy-on-write"技术。解释了String的内部构造,貌似还没有介绍String是怎么实现mutable,我们写一个Ruby扩展测试下,我们想写这样一个Ruby类:
ruby 代码
classTestdefteststr="str"str.concat("ing")endend
对应的c语言代码就是:
cpp 代码
代码如下:
#include
#include"ruby.h"staticVALUEt_test(VALUEself){
VALUEstr;str=rb_str_new2("str");
printf("beforeconcat:str:%p,
str.aux.shared:%p,str.ptr:%s"n",str,(RSTRING(str)->aux).shared,RSTRING(str)->ptr);
rb_str_cat2(str,"ing");
printf("afterconcat:str:%p,str.aux.shared:%p,str.ptr:%s"n",
str,(RSTRING(str)->aux).shared,RSTRING(str)->ptr);returnself;
}
VALUEcTest;
voidInit_string_hack(){
cTest=rb_define_class("Test",rb_cObject);
rb_define_method(cTest,"test",t_test,0);
}//string_hack.c
rb_define_class函数定义了一个类Test,rb_define_method将t_test方法以test的名称添加到Test类。在t_test中,通过rb_str_new2每次生成一个RString结构,然后通过rb_str_cat2将str与"ing"连接起来,添加了一些打印用于跟踪。利用mkmf产生Makefile,写一个extconf.rb
ruby 代码
require'mkmf'create_makefile("string_hack");
执行ruby extconf.rb,将产生一个Makefile,执行make,生成一个string_hack.so的链接库。扩展写完了,通过ruby调用:
ruby 代码
require'string_hack"t=Test.new(1..3).each{|i|t.test}
输出:
before concat: str:0x40098a40, str.aux.shared:0x3, str.ptr:str
after concat: str:0x40098a40, str.aux.shared:0x8, str.ptr:string
before concat: str:0x40098a2c, str.aux.shared:0x3, str.ptr:str
after concat: str:0x40098a2c, str.aux.shared:0x8, str.ptr:string
before concat: str:0x40098a18, str.aux.shared:0x3, str.ptr:str
after concat: str:0x40098a18, str.aux.shared:0x8, str.ptr:string
从结果可以看出,在str concat之前之后,str指向的位置没有改变,改变的仅仅是str中ptr指向的字符串的值,看看rb_str_cat2函数的实现就一目了然了:
cpp 代码
代码如下:
VALUErb_str_cat(str,ptr,len)VALUEstr;
constchar*ptr;
longlen;
{
if(len<0){rb_raise(rb_eArgError,"negativestringsize(orsizetoobig)");
}
if(FL_TEST(str,STR_ASSOC))
{
rb_str_modify(str);
REALLOC_N(RSTRING(str)->ptr,char,RSTRING(str)->len+len);
memcpy(RSTRING(str)->ptr+RSTRING(str)->len,ptr,len);
RSTRING(str)->len+=len;
RSTRING(str)->ptr[RSTRING(str)->len]='"0';
/*sentinel*/
returnstr;
}
returnrb_str_buf_cat(str,ptr,len);
}
VALUErb_str_cat2(str,ptr)VALUEstr;
constchar*ptr;
{
returnrb_str_cat(str,ptr,strlen(ptr));
}
//string.c
文章来源:
http://www.163ns.com
,转载请注明!
分享到:
复制地址
新浪微博
腾讯微博
QQ空间
开心网
人人网
百度空间
百度贴吧
网易微博
搜狐微博
上一篇:
浅谈ruby类型
下一篇:
浅谈Ruby self
相关文章:
广告联盟中的CPA、CPS、CPC、CPM分别是什么意思
云时代世界观:谁能找到位置就能抢未来的钱
中科院公布H7N9禽流感病毒源
最多点击19次即可到达任意网页
FTP主动模式/被动模式两种工作模式对比
在线咨询
客服咨询
企业qq交谈
QQ:800009888
备案专员
企业qq交谈
QQ:973907313
域名专员
企业qq交谈
QQ:6584830
在线时间
8:00-17:40