ptr_vector-一个指针的容器

 http://www.orcode.com/article/STL_20117335.html

简介

STL容器,迭代器和算法,而不是对象。值语义变得很明显的,当您尝试存储在一个标准集装箱,如指针,在一个std::vector的。你立刻感受到"阻抗失配"标准的矢量值之间的接口和存储的指针。一个额外的*(解引用)是必要的,达到指向的对象。这是烦人的,尤其是当你使用的算法。
ptr_vectorlt; TGT;是一个标准vectorlt的包装,T * GT;削减一个迭代器和成员函数的间接水平。从本质上讲,ptr_vector让你把一个指针的向量,就好像它是一个值的向量。在许多情况下,这正是你想要的。
,如果你不使用STL熟悉,在CodeProject。
ptr_vector是也。
参见代码和文章最近的变化。背景核心功能ptr_vector实现为标准C(STL)的载体的包装。迭代器遍历指向的对象,不是指针。迭代器是稳定的:ptr_vector容器扩展(标准矢量迭代器变得无效)时ptr_vector迭代器仍然有效。一些ptr_vector(即"右")的成员函数(operator []的,在(),()的前面,背面(),... ...)是指指向的对象,不是指针。不依赖第三方库 - 只是:#包括"ptr_vector.hquot;ptr_vectorlt; TGT;有相同的异常担保标准vectorlt,T * GT;成员函数提供的异常保证。ptr_vector非侵入性为指向的对象(例如,它们不需要从一个共同的基类派生)。先决条件:ptr_vector指针必须是0或NULL。
[1]为了更准确:会员功能,插入对象或脱离ptr_vector的对象有一个"指针接口",其余有一个"价值接口"。比较标准向量
一个代码片段,胜过千言万语。下面的示例比较:stdx:ptr_vectorlt; TGT;(类型T的对象的指针的一个新的容器),的std::vectorlt; TGT;(标准C类型T的对象的容器),并vectorlt,T * GT;的std::(标准C类型T的对象的指针的容器)。
以下三个代码片段打印相同的结果:你好,世界!你好,世界!你好,世界!stdx::ptr_vectorlt; TGT; ptr_vectorlt; stringgt;载体;vec.push_back(新的字符串("您好,quot;));vec.push_back(新的字符串("!世界"));法院LT,LT; VEC [0] LT,LT; vec.at(1) LT,LT; * vec.begin()LT,LT; vec.begin()[1] 0; LT,LT; vec.front()LT,LT; vec.back();:vectorlt; TGT; vectorlt; stringgt;载体;vec.push_back(字符串(quot;您好,quot;));vec.push_back(字符串("世界quot;!));法院LT,LT; VEC [0] LT,LT; vec.at(1) LT,LT; * vec.begin()LT,LT; vec.begin()[1] LT,LT; vec.front()LT,LT; vec.back();STD:vectorlt; T · GT; vectorlt;字符串* GT;载体;vec.push_back(新的字符串("您好,quot;));vec.push_back(新的字符串("!世界"));法院LT,LT; * VEC [0] LT,LT; * vec.at(1) &# 160; LT,LT; ** vec.begin()LT,LT; * vec.begin()[1] &# 160;LT,LT; * vec.front()LT,LT; * vec.back();TGT; ptr_vectorlt优势相比,vectorlt; TGT;ptr_vector不复制对象不必要的,因此它也是(不公开的拷贝构造函数和赋值运算符的对象)适用于实体对象。可容纳多态对象(例如,基类和派生对象)。有更好的异常担保(复制,而不是唯一指针指向的对象)。执行得更好(只有指针被复制,而不是...).ptr_vector扩展时,迭代器仍然有效。TGT; ptr_vectorlt相比优势vectorlt; T · GT;ptr_vector更方便,你没有看到这么​​多明星(*)在你的代码,尤其是。(STL)的算法,可用于没有特殊的比较对象直接内部,解引用指针。你不能改变一个指向一个const ptr_vectorlt对象; TGT(您可以更改指出,在一个const vectorlt对象,T * GT)。ptr_vector扩展时,迭代器仍然有效。缺点ptr_vectorlt; TGT;相比vectorlt TGT; vectorlt,T * GT;解引用一个iterator ptr_vectorlt; TGT效率略少;:迭代器vectorlt,T * GT相比;::iterator和vectorlt; TGT;:迭代器。ptr_vector的设计原则ptr_vector不构造,复制,转让,克隆,或破坏任何指向的对象。你不会失去控制指向的对象。
这是什么意思? ptr_vector往往是用来保存在堆上分配的对象(虽然它也可以包含全球或基于堆栈的对象)。 ptr_vector不提供像清晰(成员函数)和分配()这将使(特别是人迹罕至的基于堆)指向的对象被调用时,除非你有一个指针的第二个容器(另见下文)。会员功能概述功能性病::向量stdx::ptr_vector评论拷贝构造函数 - (1)=操作符(),分配() - (1)(2)开始(),rbegin() - ()的结尾,撕裂() - 调整() - (1)大小MAX_SIZE(),(),空() - ,储备容量()() - 运算符[],在() - 阵线(),回() - push_back() - pop_back() (3)插入() - - (2)(4)分离() - (4)(5)交换() 0;明确() - (2)排序() - (7)
评论:设计原则1:指向的对象不是构造,复制,分配,克隆,或通过ptr_vector销毁。设计原则2:此功能不ptr_vector提供指向的对象,因为你会失去控制。ptr_vector:pop_back()删除最后一个元素,并返回一个指向被删除的对象!使用ptr_vector:分离(以用于矢量):擦除();因为载体:擦除()返回一个迭代的第一个对象不会被删除,它违反了设计原则2。ptr_vector:分离()从容器中删除一个或多个元素(S);删除的元素是通过返回给调用者。ptr_vector:swap()的交流与ptr_vectorlt元素; TGT; vectorlt,T * GT;ptr_vector::sort()的各种指出,交换指针的对象。
你可以得到有关ptr_vector从API文档(参见下载)成员函数的更多信息。资源管理和异常安全ptr_vector_owner
ptr_vector_owner是一个可选的辅助类模板,范围后卫,ptr_vector动态创建对象的所有权(按设计,ptr_vector本身并不知道任何有关指向的对象的所有者(S))。 
"所有权"是指ptr_vector_owner在ptr_vector删除所有指向的对象时,超出范围(在其析构函数)。当然,你只需要ptr_vector_owner时,你必须用新的分配指向的对象。例子:void MYFUNC(){ ptr_vectorlt; stringgt; PTV; &# 160;ptr_vector_ownerlt; stringgt;所有者(PTV); / /范围后卫 60;ptv.push_back(新的字符串("曾几何时... ...")); / / ... IF(something.isWrong()) 抛出异常("看得真正的错误quot;); / / ... 回报;} / /指向的对象在PTV被删除!
上面的函数结束执行常规路径上的异常或返回。在这两种情况下,在ptr_vectorlt所有的对象; stringgt; PTV被删除ptr_vector_ownerlt stringgt;所有者。换句话说,ptr_vector_owner是一个著名的彗星成语的变种,叫。 建议:特设尽可能删除的对象喜欢使用ptr_vector_owner(或其他资源管理器)自动资源管理。业主(范围卫士)的工作最好的,因为在这种情况下,资源管理被封装为类成员。对象没有用户干预的情况下,如资源管理。 MyClass的{市民: MyClass的():mOwner(mPtv){} / / ...私人: ptr_vectorlt; stringgt; mPtv; ptr_vector_ownerlt; stringgt; mOwner; / /范围后卫};使用代码
下面是一个完整的例子(见下载)。例如为了使用对象的类型为std::字符串,但会做任何类(非复制)以及。完整的例子#包括LT; iostreamgt;#包括LT; stringgt;#quot; ptr_vector.hquot;使用命名空间std; / /为法院,endl,查找,替换.../ /使用命名空间stdx; ptr_vector,ptr_vector_owner主要INT(){ 60; 法院LT,LT; quot ;---- ptr_vector演示---- quot; LT,LT; endl; ptr_vectorlt; stringgt; PTV; ptr_vector_ownerlt; stringgt;所有者(PTV); / /范围后卫:- ED新对象的所有者 ptv.push_back(新的字符串("; Peterquot";)); & #160;ptv.push_back(新的字符串("; Paulquot";)); ptv.insert(ptv.end(),新的字符串("; Margaretquot";)); 法院LT,LT;"1:"LT,LT; ptv.front()LT,LT;""LT,LT; ptv.back()LT,LT; endl; 法院LT,LT;"2:"LT,LT; PTV [1](2)LT,LT;""LT,LT; ptv.at LT,LT; endl; 法院LT,LT;"3:"LT,LT; * ptv.begin()LT,LT;""LT,LT; *(ptv.begin(1))LT; <endl; 法院lt,lt;"4";="" &="" #160;="" (ptr_vectorlt;="" stringgt;:迭代="ptv.begin();" =="" ptv.end();吧!)="" 法院lt,lt;""lt,lt;它;="" 法院<<endl;="" ptv.sort();="" 法院lt,lt;"5:"lt,lt;="" ptv="" [0]="" lt,lt;""lt,lt;="" [1]="" [2="" ]="" <<endl;="" ptv.sort(greaterlt;="" stringgt="" ;());="" 法院lt,lt;"6:"lt,lt;="" ptr_vectorlt;="" stringgt;:迭代iter;="" iter="(ptv.begin(),ptv.end(),"Paulquot);" (iter="ptv.end())!" 法院lt,lt;"7:"lt,lt;="" *="" lt,lt;="" endl;="" 取代(ptv.begin="" ptv.end()(),字符串("paulquot),字符串("fredquot;));="" 法院lt,lt;"8:"lt,lt;="" ptv.begin()[1]="" lt;="" <endl;="" 字符串*="" str="ptv.pop_back();" 法院lt,lt;"9:"lt,lt;="" lt,lt;"="" -="" 大小:"lt,lt;="" ptv.size()lt,lt;="" ="" 60;删除str;="" 删除ptv.detach(ptv.begin());="" 法院lt,lt;"10:"lt,lt;="" stringgt;="" ptvtwo;="" ptr_vector_ownerlt;="" ownertwo(ptvtwo);&#="" 160;="" ptvtwo.push_back(新的字符串(";="" elisabethquot";));="" susanquot";));="" ptv.swap(ptvtwo);="" (ptv="" ptvtwo)="" 法院lt,lt;"11:"lt,lt;="" ptv.begin()lt,lt;"="" ptv.size(lt);="" 返回0;}
程序的输出:ptr_vector演示---- ---- 1:彼得玛格丽特 2:保罗玛格丽特 3:彼得保罗 4:彼得保罗玛格丽特 5:玛格丽特保罗彼得 6:彼得保罗玛格丽特 7:保罗 8:弗雷德& #160; 9:玛格丽特 - 大小:2 弗雷德 - 10:大小:1 11:伊丽莎白 - 大小:2ptr_vector和标准算法问题
考虑下面的例子:ptr_vectorlt; MyClassgt; PTV;ptr_vector_ownerlt; MyClassgt;所有者(PTV);/ /插入PTV元素...STD:stable_sort(ptv.begin(),ptv.end()); / /交流MyClass的对象:(
stable_sort是一个标准的算法,传递范围内的各种元素保持相等元素的相对顺序。在上面的例子,算法低效交流(拷贝)指向的对象,在stable_sort(MyClass的对象)。但它应该只交换指针!
这同样适用于所有的算法,重新排列序列中的元素。目前尚无有效的方式来改变所需的标准算法的行为。 ptr_vector,这似乎是一个值的向量的指针的向量,只是工作不太好,在这种情况下。我们如何保持当前的方便的接口和标准算法的高效工作的根本指针?解决方案
修改后的例子:ptr_vectorlt; MyClassgt; PTV;ptr_vector_ownerlt; MyClassgt;所有者(PTV);/ /插入PTV元素...stdx:stable_sort(ptv.begin(),ptv.end()); / /交流指针  ; / / MyClass的对象!
的差异,以前面的例子可以很容易被忽视。 stable_sort算法从命名空间stdx的命名空间std算法是用来代替。 (ptr_vector还驻留在命名空间stdx)
其实,stdx:stable_sort仅仅是一个对性病瘦包装:stable_sort,引擎盖下的"正确的事":它的顺序进行排序,交换指针,而不是指向的对象。在命名空间stdx中的算法包裹算法的工作像ptr_vector指针迭代器:迭代器。只重新排列元素序列的算法,包装成为"指针知道"。非变异的算法比如std::发现不和不需要包裹,他们的工作,因为它们。已被删除,remove_if,以及独特的指针迭代器实现的,因为标准的实现不工作在这些案件中的指针(他们不工作的顺利开展与价值观,无论是)。这些算法现在只删除或覆盖的任何元素的元素进行重新排序。包装是一个简单和统一的方式进行。通常情况下,被添加到一个间接层的参数,才传递到底层的标准算法。因此,可以假设包裹算法如裹的可靠的标准算法。包裹算法列表:swap_ranges,相反,旋转,random_shuffle,分区,stable_partition,排序stable_sort,partial_sort,nth_element,inplace_merge,push_heap,pop_heap,make_heap,sort_heap,next_permutation,prev_permutation使用提示:排序算法要求operatorlt;定义为指向的对象,或者说是一个比较对象作为第三个参数传递。对于其他算法,运算符==可能是必要的。始终指出对象与检查算法的要求,在使用它之前。违反规定,通常会产生一个STL是臭名昭著的一堆难以理解的编译器错误信息。两全其美
我们已经得到了无论是现在,仅仅是重新排列指针引擎盖下和方便处理表面上的值的效率。标准算法库ptr_vector迭代器,可以直接(不交换元素的算法,)或薄包(重新排列算法)。
高级用户可以编写他们自己的算法标准迭代器和指针迭代器都使用类似标准迭代特征(见单元测试的一个例子)中发明的编译时间派遣技术工作。兴趣点单元测试
ptr_vector,ptr_vector迭代器和算法提供的单元测试(见下载)。他们不仅检查执行的正确性,但也可作为:如何用ptr_vector程序和例子如果你想使用或到一个新的编译器的端口ptr_vector ptr_vector的(虽然有问题的模板构造是可以避免的,期望的编译器和标准库不兼容)的援助。
单元测试已经证明,发展中国家和重构的代码和模板代码一般是必不可少的。通常,编译器甚至没有(彻底)语法检查,除非实际上是一个模板函数实例化。优化
ptr_vector的实现是基于标准C向量。它使用的vectorlt; T · GT;在调试模式(调试版本)和一个vectorlt;无效* GT在Release模式(发布版本)的基础容器。这就避免了在发布程序的模板"代码膨胀"。请注意,始终是强类型的ptr_vector的接口(包括迭代器)。优化内部只发生。编译器兼容性
单元测试成功编译和运行:VC + + 6.0(几种替代方法,特别是为VC 6.0实现)VC + + NET 7.1,8.0GCC 3.2,3.4(Windows)中,3.3,4.0(Linux)的EDG编译器使用网上。
除了从平时的不兼容性,ptr_vector应与大多数编译,至少温和,符合标准的C编译器和标准库。请我一张纸条,如果您有没有在上面列出的编译器编译的测试案例,也(especially!)如果您遇到编译时的错误,从而。顺便说一下,多年后,彗星标准化(1998年),编译器生产商(商业和非商业)仍然改变模板加工与每一个轻微的释放。这个事实本身表明在C模板机制的严重问题。历史注释
各种容器和指针迭代器已生产库供应商和个人开发者,基于STL的或不。例如:,,,,,,,,,... ...
C标准由于缺乏对指针的容器,可能很多自制的实现存在。谢谢
非常感谢安德烈亚斯R.本文的审阅,并用VC编译的代码的。NET 7.1。结论
ptr_vector主要目的是使在STL的容器更方便了用户的处理对象(指针)。 ptr_vectorlt; TGT;接近标准vectorlt; TGT;接口和使用方面 - 有没有需要学习一门新的"范式"。裹标准算法方便,快捷的方式,重新排列序列。 ptr_vector_owner提供了一个易于使用的正常和特殊情况下的默认资源管理器。网上资源他说:""(注:只有一个STL的一个子集,包括C标准)。"历史2004年6月6日 - 提交CodeProject上2004年12月16日 - 更新版本提交给在CodeProject实施ptr_vector迭代器包裹算法增加包裹算法的测试用例代码清理了文章:章"ptr_vector和标准算法"添加文章修改和清理2005年3月14日 - 更新版本提交给在CodeProject邮编:私有继承下降由于在迭代执行新模板查找规则(2相名称查找)由GCC 3.4执行;这个重构不影响"外"的行为文章:小的改动和更正2006年10月21日 - 更新版本提交给在CodeProject邮编:较新的编译器版本的测试与代码文章:更新的无效链接小的改动和更正
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C++智能指针 ⼀ ⼀. 智能指针 智能指针 在 C++ 中,我们申请内存⼀般使⽤ new,释放内存时使⽤ delete,但是有时候我们可能由于疏忽会忘记 delete,或者当程序有多个 出⼝时,也会容易有 new 没有 delete,这样就产⽣了内存泄漏,如果你的程序是⼀个需要长期运⾏的服务器程序,可能运⾏着⼏天突然程 序就崩溃了,原因也不好定位,所以为了⽅便内存管理,C++ 引⼊了智能指针,智能指针的优点在于能够帮助程序员⾃动释放我们 new 出 来的堆内存。 C++ 标准库有四种智能指针:auto_ptr,unique_ptr,shared_ptr,weak_ptr(auto_ptr 是 C++98 标准的,其余都是 C++11 标准推出的,auto_ptr 现在已经不再使⽤了),C++11 这三种智能指针都是类模板。 ⼆ ⼆. shared_ptr (⼀)概述 (⼀)概述 shared_ptr 是⼀个共享式指针,所有的 shared_ptr 共享对指向内存的所有权,不是被⼀个 shared_ptr 拥有,⽽是多个 shared_ptr 之间互相协作。 (⼆)⼯作原理 (⼆)⼯作原理 引⽤计数,use_count 为 0 时就释放对象空间。 (三)初始化 (三)初始化 如果是定义了⼀个智能指针却不初始化,shared_ptr<int> p1,代表定义了⼀个指向 int 类型对象的智能指针但是⽬前指向为 empty。推荐使⽤ make_shared 函数来初始化 shared_ptr,它是标准库的函数模板,安全,⾼效地分配和使⽤ shared_ptr。 shared_ptr<int> pint = make_shared<int>(100); shared_ptr<string> pstr = make_shared<string>(5,'a'); 也可以使⽤直接初始化的⽅式 shared_ptr<int> pint(new int(100)) 来创建⼀个 shared_ptr 并初始化,但是由于 shared_ptr 定义 的构造函数是 explicit 的,因此不能使⽤ shared_ptr<int> pint = new int(100) 来创建⼀个 shared_ptr 并初始化,因为这种⽅式隐式要 求将⼀个普通的 int * 转换为 shared_ptr<int>。 (四)常⽤操作 (四)常⽤操作 1. use_count 返回多少个智能指针指向该对象,主要⽤于调试。 2. unique 判断该智能指针是否独占该内存,如果该智能指针不指向任何对象,判断 unique 的时候也是假。 3. reset 不带参数时:放弃指针对对象的掌管权,重置为 nullptr 带参数时:参数⼀般是⼀个 new 的空间,相当于放弃指针对当前对象的掌管权,然后将指针指向 new 出来的空间。 4. * 解引⽤,可以获取指针指向的对象。 5. get 获取指针指针⾥保存的裸指针,⼀般⽤于⼀些接⼝需要使⽤到 C 语⾔指针的情况。 6. swap 交换两个智能指针所指的对象。 7. =nullptr 该智能指针指向 nullptr,代表解除对该对象的掌握权,引⽤计数将会减1,如果此时该内存空间的引⽤计数变为0,会同时释放该内存。 8. 指定删除器以及删除数组问题 指定删除器以及删除数组问题 智能指针能在⼀定时机帮我们删除所指向的对象,使⽤ delete 作为默认的资源析构⽅式,我们也可以指定⾃⼰的删除器取代系统提供的默 认删除器,当智能指针需要删除所指向的对象时,编译器就会调⽤我们提供的删除器。 shared_ptr 指定删除器的⽅法⽐较简单,⼀般只需要在参数中添加具体的删除器函数即可。如果提供了删除器,那么就需要⼿动删除资 源,否则会造成内存泄漏。删除器函数可以是函数,lambda 表达式,重载了 operator() 的类等。 还可以使⽤ default_delete 来做删除器,default_delete 是标准库⾥的⼀个模板类。如:shared_ptr<A> p3(new A[10], default_delete<A[]>()),这样就知道我们使⽤智能指针指向了⼀个对象数组,这样就可以正确释放了。 其实,使⽤ shared_ptr 指向对象数组不需要通过删除器的⽅式,只需要在定义 shared_ptr 时指为数组类型即可,如:shared_ptr<A[]> p4(new A[10])。 额外说明:就算是两个 shared_ptr 指定了不同的删除器,只要他们指向的对象类型相同,那么这两个 shared_ptr 也是同⼀个类型,可以 放到同⼀个容器去,vector<shared_ptr<int>> pvec{p1,p2}。 三 三

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值