免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: xiaomiao
打印 上一主题 下一主题

使用class template扩展STL map容器类对象的一个例子 [复制链接]

论坛徽章:
0
21 [报告]
发表于 2006-10-03 14:18 |只看该作者
使用引用语义还是感觉极度诡异
此外你的两个add就是两个不同的语义
add(const T&)内部是一个深拷贝
add(T*)则是浅拷贝
考虑这样的代码container1.add(container2.add(new int(10)))
在释放的时候会怎么样呢?

论坛徽章:
0
22 [报告]
发表于 2006-10-03 14:33 |只看该作者
呵呵,我说了,两个 add 语意不同。提交指针时,指针指向的对象应该由容器的 Factory 得到;提交后,返回的是一个指向容器内对象的指针,算是一个 weak reference。提交 const ref 纯粹为了兼容 STL 语意,进行一个深复制。实际上,这个接口是我在发帖的适合临时加入的:)

  1. container1.add(container2.add(new int(10)))
复制代码

这个代码中,new int(10) 首先没有使用 container2 的 Factory 生成,此是一错
new int 得到的指针被提交给 container2,因此不会有内存泄漏
而 container2.add 返回的是一个 weak reference,你将这个 weak reference 再次『提交』给 container1,自然是会出现运行错误的。

论坛徽章:
0
23 [报告]
发表于 2006-10-03 14:51 |只看该作者
首先,C++没有weak reference的概念
你的add(T*)接口没有规定我是从哪分配来的内存,即便是add(new int (Factory<int>::newInstance()) (10))我仍然添加的是指针,而且这个指针指向了一块内存

第二,我所给出的代码并不会出现运行时错误,也不会内存泄漏;相反,是在释放的时候出现delete 空指针
不管你的对象是从什么地方分配来的,只要是个指针,那么被提交给两个你的容器里之后,就必然在析构的时候delete null_pointer,其实这跟你把auto_ptr放进vector里面是一个问题

第三,防止以上问题出现只有两个方法:要么用add(const T&),但这就是一个值语义,因为你使用了深拷贝,你在内存使用上一点儿也不省;要么增加对对象指针的所有权管理,考虑到具体类的设计者很可能会用到RAII,你只能使用引用计数,也就是shared_ptr

我看了你在csdn上的那个帖子,似乎根本上来说,就是你对把auto_ptr放入vector里面念念不忘,但这不行

论坛徽章:
0
24 [报告]
发表于 2006-10-03 15:30 |只看该作者
首先,C/C++ 没有的概念多了,包括 C 没有『字符串』,包括 C++ 没有 concept。很多东西都是一个约定而已。我这个容器约定,提交的指针应该由与容器相同的 Factory 构造;不满意,可以交给我的容器负责自己构造一个。
其次,你把一个指针提交给两个容器根本就是错误的做法。一稿多投在很多出版社都是不受欢迎的。析构时候不会出现 delete null_pointer,而是出现 double dtor / double free。这和 vecter<auto_ptr<T> > 是完全不同的。
第三,内存节省和节省对象复制方面的问题主要出在 vector / deque 缓存的重新分配方面,因为这个过程可能重复的、大量对象的复制。提交 const ref 是出于接受常量或常引用等不可提交对象而准备的,如 container<int> c; c.add(1); 这种情况。

Rules and contracts are to be obey, not to be challenged. Or, go ahead and write
  1. strcpy("String", NULL);
复制代码

[ 本帖最后由 wolf0403 于 2006-10-3 15:39 编辑 ]

论坛徽章:
0
25 [报告]
发表于 2006-10-03 16:15 |只看该作者
我这个容器约定,提交的指针应该由与容器相同的 Factory 构造;不满意,可以交给我的容器负责自己构造一个。

我之所以用placement operator new就是告诉你不管谁构造都是一个意思

你把一个指针提交给两个容器根本就是错误的做法。

不要说你的容器不能使用标准算法,我可是要std::copy的

内存节省和节省对象复制方面的问题主要出在 vector / deque 缓存的重新分配方面

出现重新分配是你程序写得不好,不确定容量就得用reserve,push_front就不能用vector,这都不知道那就没办法了

你始终没能解决把你的容器作为范化容器使用的问题,如果你需要让使用你代码的人接受一千条规定的话,那就没必要讨论了

论坛徽章:
0
26 [报告]
发表于 2006-10-03 16:30 |只看该作者
1、placement new?抱歉,没注意到您在哪里谈到过。

2、是不是除了我的容器,std::copy 已经兼容天下所有容器库了?还是只有当那些容器属于对 STL 的扩充的时候,std:: 的算法才能应用呢?一个框架有一个框架的范围,我说了,我的容器不属于 STL 框架,也不兼容 STL 框架,因为从语意到设计思路都是不同的。

3、呵呵,就像您有意将一个对象分别提交给我的两个容器,我为什么不能对 vector 进行 push_front?编译器并没有阻止我,不是么?

您所谓的范化,始终仅限于 STL 框架内。我即使另写一套值语意的容器,仍然可以做到不兼容 STL。
使用 STL 容器和算法,我需要精心设计我的对象(或容器和迭代器,如果要兼容 std algorithm),通过(个人认为丑陋而多余的)操作符重载来达到 STL 容器中暗含的某些奇特要求,这可比我的容器所做出的约定数量更多多且不可理喻多了。

如果反对我的观点,请您告诉我:
为什么 STL 不允许我对 map 和 set 执行 remove_if ?
是标准委员会的老爷们认为说从 map 或 set 中有选择删除某些对象是完全无理取闹的行为么?

论坛徽章:
0
27 [报告]
发表于 2006-10-03 16:48 |只看该作者
1. 麻烦您仔细看我写的代码

2. 那告诉我您的那个容器是干什么的?就为了让您后面的main能编译运行是么?

3. vector.push_front可不会去玩空指针,效率低下与dump不是一个概念

你把引用语义用于STL自然会遇到各种各样的隐晦、丑陋且多余的编译器报告,自己用多余的概念写多余的库

你永远要满足语义的需求,正像list还提供了自己的sort,这就是list和sort共同表达的意思

你维护了一个脆弱,孤独,不和任何库相同的指针集合;即把最珍贵的资源委托于他人,又让你同时有能力去疯狂的摆弄;你的指针不能delete,不能放到不同的容器中,不能应用于已有的算法

仅仅为了减少一个4字节的引用计数而重写整套库,这到底是去反抗委员会老爷们的圣旨,还是精力过剩?

论坛徽章:
0
28 [报告]
发表于 2006-10-03 17:08 |只看该作者
1、代码太多了,您提示一下方便大家不可以么?恕我眼拙,我确实没有找到任何一个代码中出现过 placement new 。

2、第 N+1 次向您解释这个问题:我的代码只是一个片段,并没有形成一个完整的框架,所以要求实现所有的算法是不切实际的。如果真的有人有兴趣,我大可以把整个 STL 移植到我的这个框架上来。

3、再次告诉您,首先,我这里也没有空指针。其次,效率低下和错误当然不是一个概念。相比效率低下的代码,出错的代码更容易引起程序员的警觉。除非 STL 是在鼓励程序员『实现功能就行,效率是可有可无的东西』,否则只能说 STL 在这点上反而不如我的框架对程序员提供了更多的帮助。

4、关于『各种各样的隐晦、丑陋且多余的编译器报告』,能否请给出几个例子?

5、请问您说的『语义的需求』是谁的需求?是程序员、对象本身,还是 STL?为什么 map 和 set 不能有选择删除元素?

6、指针和对象是两个概念。根据我默认提供的一组 Factory / Dtor,这个容器是通过指针管理对象;而如果你需要另外一个容器来操作指针,可以重写一组 Factory / Dtor,也可以使用 STL ——当不需要通过指针、描述符或者其它相对复杂的机制管理对象而仅仅是直接摆弄几个对象的时候,STL 的确做得很好。

7、我的方案保证了在使用我的容器管理对象的同时,可以通过最直接的方式使用这些对象。如果你认为 shared_ptr<T> 和 T 的区别只是一个 4bytes / object 的 space overhead,那么我只能认为您或者是在有意忽略一个额外间接层带来的设计复杂性、函数调用和指针转发带来的效率损失或内联、模版带来的代码膨胀;或者您确实一窍不通

我可以接受您不理解我的设计,但是如果您只是一味地攻击却指不出更实质的设计缺陷,我只能选择沉默。

论坛徽章:
0
29 [报告]
发表于 2006-10-03 17:37 |只看该作者
额外的中间层解决了大量的软件问题
似乎你也没看到COM取得了多少成就以及他被取代的根本问题
你的设计问题就是你根本不应该设计这个东西,你期望能用一个管理器去管理一个给定粒度上的所有动态内存分配工作而又不付出任何代价

我从你所给出的全部代码中只能看出这根本就不是一个容器,而是让你可以把在时间上接近,用处相同的指针进行自动管理,然后随意的使用而不但心析构问题
承认吧,按照你的说法,与其是容器,不如说是个内存管理器;你一直在避讳我提出的实际代码问题,只说一句“我的代码不跟这些东西交流”,那你的代码干什么?

你说你可以实现整个你风格STL,我不是怀疑,而是根本不信,因为我从你给出的代码和描述上看不出一点儿能重用的地方

set map不能原地修改才是他不能remove_if的原因。那不能把元素添加到两个你的容器的原因是什么?是因为你那个东西根本就不是容器,而是内存管理器,不管你怎么把Dtor/Ctor分出来

至于指针转发,内联等问题,还是先看看shared_ptr的源码和编译器的行为再说吧

ps. 好吧我承认你那是一个非常卓越的容器,那么我可不可以把所有我new出来的东西都扔里面,然后庄严的宣告,我实现了C++下的垃圾收集?

论坛徽章:
0
30 [报告]
发表于 2006-10-03 18:12 |只看该作者
前面的不讨论了,没说头,我只当你在搞笑。
如果
set map不能原地修改才是他不能remove_if的原因
,为什么 map 和 set 仍然支持 erase 一个 iterator?

好吧我承认你那是一个非常卓越的容器,那么我可不可以把所有我new出来的东西都扔里面,然后庄严的宣告,我实现了C++下的垃圾收集?

不妨去看看《C++沉思录》里的第 28 章……荣誉归于圣 Andrew Koenig 和圣 Barbara Moo

[ 本帖最后由 wolf0403 于 2006-10-3 18:16 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP