﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-doing5552</title><link>http://www.cppblog.com/doing5552/</link><description>记录每日点滴，不枉人生一世</description><language>zh-cn</language><lastBuildDate>Tue, 07 Apr 2026 11:36:29 GMT</lastBuildDate><pubDate>Tue, 07 Apr 2026 11:36:29 GMT</pubDate><ttl>60</ttl><item><title>再次更新一下</title><link>http://www.cppblog.com/doing5552/archive/2015/03/16/210065.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Mon, 16 Mar 2015 15:45:00 GMT</pubDate><guid>http://www.cppblog.com/doing5552/archive/2015/03/16/210065.html</guid><wfw:comment>http://www.cppblog.com/doing5552/comments/210065.html</wfw:comment><comments>http://www.cppblog.com/doing5552/archive/2015/03/16/210065.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/doing5552/comments/commentRss/210065.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/doing5552/services/trackbacks/210065.html</trackback:ping><description><![CDATA[年近三十了，再次把这个博客拾起来吧。<br />距离毕业也已经近五年了，现在也实现了一些刚刚开始工作的目标。<br />不过离最终的目标还有很远的距离，继续加油吧，完善自己！<img src ="http://www.cppblog.com/doing5552/aggbug/210065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/doing5552/" target="_blank">doing5552</a> 2015-03-16 23:45 <a href="http://www.cppblog.com/doing5552/archive/2015/03/16/210065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>联合(union)用法</title><link>http://www.cppblog.com/doing5552/archive/2013/01/05/196966.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Sat, 05 Jan 2013 03:45:00 GMT</pubDate><guid>http://www.cppblog.com/doing5552/archive/2013/01/05/196966.html</guid><wfw:comment>http://www.cppblog.com/doing5552/comments/196966.html</wfw:comment><comments>http://www.cppblog.com/doing5552/archive/2013/01/05/196966.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/doing5552/comments/commentRss/196966.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/doing5552/services/trackbacks/196966.html</trackback:ping><description><![CDATA[<div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">联合(union)在C/C++里面见得并不多，但是在一些对内存要求特别严格的地方，联合又是频繁出现，那么究竟什么是联合、怎么去用、有什么需要注意的地方呢？就这些问题，我试着做一些简单的回答，里面肯定还有不当的地方，欢迎指出！&nbsp;<br style="padding: 0px; margin: 0px;" /><strong style="padding: 0px; margin: 0px;">1、什么是联合？</strong><br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp; &#8220;联合&#8221;是一种特殊的类，也是一种构造类型的数据结构。在一个&#8220;联合&#8221;内可以定义多种不同的数据类型， 一个被说明为该&#8220;联合&#8221;类型的变量中，允许装入该&#8220;联合&#8221;所定义的任何一种数据，这些数据共享同一段内存，已达到节省空间的目的（还有一个节省空间的类型：位域）。 这是一个非常特殊的地方，也是联合的特征。另外，同struct一样，联合默认访问权限也是公有的，并且，也具有成员函数。</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;"><strong style="padding: 0px; margin: 0px;">2、联合与结构的区别？</strong><br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp; &#8220;联合&#8221;与&#8220;结构&#8221;有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间， 一个结构变量的总长度是各成员长度之和（空结构除外，同时不考虑边界调整）。而在&#8220;联合&#8221;中，各成员共享一段内存空间， 一个联合变量的长度等于各成员中最长的长度。应该说明的是， 这里所谓的共享不是指把多个成员同时装入一个联合变量内， 而是指该联合变量可被赋予任一成员值，但每次只能赋一种值， 赋入新值则冲去旧值。</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">&nbsp;&nbsp; 下面举一个例了来加对深联合的理解。&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 例4:</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">#include &lt;stdio.h&gt;<br style="padding: 0px; margin: 0px;" />void main()<br style="padding: 0px; margin: 0px;" />{<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; union number<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*定义一个联合*/<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*在联合中定义一个结构*/<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char first;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char second;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }half;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }num;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; num.i=0x4241;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*联合成员赋值*/<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%c%c\n", num.half.first, num.half.second);<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; num.half.first='a';&nbsp;&nbsp; /*联合中结构成员赋值*/<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; num.half.second='b';<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%x\n", num.i);<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getchar();<br style="padding: 0px; margin: 0px;" />}<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 输出结果为:&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; AB&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; 6261&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 从上例结果可以看出: 当给i赋值后, 其低八位也就是first和second的值; 当给first和second赋字符后, 这两个字符的ASCII码也将作为i 的低八位和高八位。</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;"><strong style="padding: 0px; margin: 0px;">3、如何定义？</strong><br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp; 例如：<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; union test<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; {<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test() { }<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int office;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char teacher[5];<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; };&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 定义了一个名为test的联合类型，它含有两个成员，一个为整型，成员名office；另一个为字符数组，数组名为teacher。联合定义之后，即可进行联合变量说明，被说明为test类型的变量，可以存放整型量office或存放字符数组teacher。</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;"><strong style="padding: 0px; margin: 0px;">4、如何说明？</strong><br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp; 联合变量的说明有三种形式：先定义再说明、定义同时说明和直接说明。<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp; 以test类型为例，说明如下：<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 1) union test<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int office;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char teacher[5];<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; union test a,b;&nbsp;&nbsp;&nbsp; /*说明a,b为test类型*/<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 2) union test<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int office;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char teacher[5];<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } a,b;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 3) union&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int office;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char teacher[5];<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } a,b;&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 经说明后的a,b变量均为test类型。a,b变量的长度应等于test的成员中最长的长度，即等于teacher数组的长度，共5个字节。a,b变量如赋予整型值时，只使用了4个字节，而赋予字符数组时，可用5个字节。</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;"><strong style="padding: 0px; margin: 0px;">5、如何使用？</strong><br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp; 对联合变量的赋值，使用都只能是对变量的成员进行。联合变量的成员表示为：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">联合变量名.成员名&nbsp;<br style="padding: 0px; margin: 0px;" />例如，a被说明为test类型的变量之后，可使用a.class、a.office&nbsp;</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">不允许只用联合变量名作赋值或其它操作，也不允许对联合变量作初始化赋值，赋值只能在程序中进行。<br style="padding: 0px; margin: 0px;" />还要再强调说明的是，一个联合变量，每次只能赋予一个成员值。换句话说，一个联合变量的值就是联合变员的某一个成员值。</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;"><strong style="padding: 0px; margin: 0px;">6、匿名联合</strong><br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp; 匿名联合仅仅通知编译器它的成员变量共同享一个地址,而变量本身是直接引用的,不使用通常的点号运算符语法.例如：<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; ＃i nclude &lt;iostream&gt;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; void main()<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; {<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; union{&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int test;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char c;&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test=5;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c=&#8242;a&#8242;;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout&lt;&lt;i&lt;&lt;" "&lt;&lt;c;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; }<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 正如所见到的,联合成分象声明的普通局部变量那样被引用,事实上对于程序而言,这也正是使用这些变量的方式.另外,尽管被定义在一个联合声明中,他们与同一个程序快那的任何其他局部变量具有相同的作用域级别.这意味这匿名联合内的成员的名称不能与同一个作用域内的其他一直标志符冲突.<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 对匿名联合还存在如下限制:<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 因为匿名联合不使用点运算符，所以包含在匿名联合内的元素必须是数据,不允许有成员函数，也不能包含私有或受保护的成员。还有,全局匿名联合必须是静态(static)的，否则就必须放在匿名名字空间中。</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;"><strong style="padding: 0px; margin: 0px;">7、几点需要讨论的地方：</strong><br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp; 1、联合里面那些东西不能存放？<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们知道，联合里面的东西共享内存，所以静态、引用都不能用，因为他们不可能共享内存。<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp; 2、类可以放入联合吗？<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们先看一个例子：<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Test<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; Test():data(0) { }<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private:<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int data;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp; typedef union _test<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; {<br style="padding: 0px; margin: 0px;" />Test test;&nbsp;&nbsp;&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; }UI;&nbsp;&nbsp;&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; 编译通不过，为什么呢？<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; 因为联合里不允许存放带有构造函数、析够函数、复制拷贝操作符等的类，因为他们共享内存，编译器无法保证这些对象不被破坏，也无法保证离开时调用析够函数。<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 3、又是匿名惹的祸？？<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们先看下一段代码：&nbsp;<br style="padding: 0px; margin: 0px;" />class test<br style="padding: 0px; margin: 0px;" />{<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test(const char* p);<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test(int in);<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const operator char*() const {return</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">data.ch;}<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; operator long() const {return data.l;}<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private:<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; enum type {Int, String };<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; union&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; {<br style="padding: 0px; margin: 0px;" />const char* ch;<br style="padding: 0px; margin: 0px;" />int i;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }datatype;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type stype;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test(test&amp;);<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test&amp; operator=(const test&amp;);<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test::test(const char *p):stype</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">(String),datatype.ch(p)&nbsp;&nbsp;&nbsp;&nbsp; { }<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test::test(int in):stype(Int),datatype.l(i)&nbsp;&nbsp;&nbsp;&nbsp; {</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">}<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; 看出什么问题了吗？呵呵，编译通不过。为什么呢？难道datatype.ch(p)和datatype.l(i)有问题吗？<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; 哈哈，问题在哪呢？让我们来看看构造test对象时发生了什么，当创建test对象时，自然要调用其相应的构造函数，在构造函数中当然要调用其成员的构造函数，所以其要去调用datatype成员的构造函数，但是他没有构造函数可调用，所以出</div><div style="margin: 0px; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">错。<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp; 注意了，这里可并不是匿名联合！因为它后面紧跟了个data!&nbsp;<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp; 4、如何有效的防止访问出错？<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用联合可以节省内存空间，但是也有一定的风险：通过一个不适当的数据成员获取当前对象的值！例如上面的ch、i交错访问。<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为了防止这样的错误，我们必须定义一个额外的对象，来跟踪当前被存储在联合中的值得类型，我们称这个额外的对象为：union的判别式。<br style="padding: 0px; margin: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个比较好的经验是，在处理作为类成员的union对象时，为所有union数据类型提供一组访问函数。</div><img src ="http://www.cppblog.com/doing5552/aggbug/196966.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/doing5552/" target="_blank">doing5552</a> 2013-01-05 11:45 <a href="http://www.cppblog.com/doing5552/archive/2013/01/05/196966.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>POSIX 线程</title><link>http://www.cppblog.com/doing5552/archive/2012/12/31/196877.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Mon, 31 Dec 2012 08:06:00 GMT</pubDate><guid>http://www.cppblog.com/doing5552/archive/2012/12/31/196877.html</guid><wfw:comment>http://www.cppblog.com/doing5552/comments/196877.html</wfw:comment><comments>http://www.cppblog.com/doing5552/archive/2012/12/31/196877.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/doing5552/comments/commentRss/196877.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/doing5552/services/trackbacks/196877.html</trackback:ping><description><![CDATA[<div style="font-family: Simsun; font-size: medium; line-height: normal; background-color: #ffffff;"><div ibm-content-expand=""  dwwordmark"="" id="ibm-content-head" style="margin: 0px; padding-top: 2px; width: 730px; background-image: url(http://dw1.s81c.com/i/c.gif); background-position: 99% 0px; background-repeat: no-repeat no-repeat;"><p style="font-family: arial, nsimsun, sans-serif; height: 18px; line-height: 1em; margin: 0px; padding: 0px 0px 8px;"><em style="font-weight: bold; font-size: 0.75em; font-style: normal; color: #666666;">POSIX 线程详解、POSIX 线程编程、NPTL</em></p></div></div><div id="ibm-content-body" style="font-family: Simsun; font-size: medium; line-height: normal; background-color: #ffffff;"><div id="ibm-content-main" style="float: left; clear: left; width: 530px;"><div ibm-alternate-six"="" style="margin: 0px 0px 1.2em; width: 530px; border-top-width: 4px; border-top-style: solid; border-top-color: #cccccc;"><div ibm-text"="" style="background-image: url(http://1.www.s81c.com/i/v16/t/sprites-t1.gif); float: left; clear: both; margin-bottom: 0px; width: 530px; background-position: 0% -725px; background-repeat: repeat no-repeat;"><h2>Page navigation</h2><div style="background-image: url(http://1.www.s81c.com/i/v16/t/text-tabs-bg.gif); background-color: #f7f8fc; border: 1px solid #cccccc; background-position: initial initial; background-repeat: repeat no-repeat;"><div ibm-first"=""><ul style="list-style-type: none; margin: 0px; padding: 5px 0px 2px; clear: both;"><li style="font-family: arial, nsimsun, sans-serif; height: 19px; padding: 0px; margin: 0px;"><a href="http://www.ibm.com/developerworks/cn/linux/theme/posix_thread/#firstmajorhead" style="color: #996699; display: block; margin: 0px; padding: 0px 5px 3px 21px; font-size: 0.8em; height: 16px; text-decoration: initial; background-image: url(http://1.www.s81c.com/i/v16/icons/d_bold.gif); background-position: 2px 0px; background-repeat: no-repeat no-repeat;">Linux 线程模型</a></li><li style="font-family: arial, nsimsun, sans-serif; height: 19px; padding: 0px; margin: 0px;"><a href="http://www.ibm.com/developerworks/cn/linux/theme/posix_thread/#secondmajorhead" style="color: #996699; display: block; margin: 0px; padding: 0px 5px 3px 21px; font-size: 0.8em; height: 16px; text-decoration: initial; background-image: url(http://1.www.s81c.com/i/v16/icons/d_bold.gif); background-position: 2px 0px; background-repeat: no-repeat no-repeat;">POSIX 线程详解</a></li><li style="font-family: arial, nsimsun, sans-serif; height: 19px; padding: 0px; margin: 0px;"><a href="http://www.ibm.com/developerworks/cn/linux/theme/posix_thread/#thirdmajorhead" style="color: #996699; display: block; margin: 0px; padding: 0px 5px 3px 21px; font-size: 0.8em; height: 16px; text-decoration: initial; background-image: url(http://1.www.s81c.com/i/v16/icons/d_bold.gif); background-position: 2px 0px; background-repeat: no-repeat no-repeat;">Posix 线程编程指南</a></li></ul></div></div><div style="clear: both; background-image: url(http://1.www.s81c.com/i/v16/t/text-tabs-drop.gif); height: 6px; border-left-color: #cccccc; border-left-style: solid; border-left-width: 1px; border-right-color: #cccccc; border-right-style: solid; border-right-width: 1px; background-repeat: repeat no-repeat;"></div></div><div style="background-image: url(http://1.www.s81c.com/i/v16/t/container-gradient.gif); border-bottom-color: #cccccc; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: #cccccc; border-left-style: solid; border-left-width: 1px; border-right-color: #cccccc; border-right-style: solid; border-right-width: 1px; background-position: 0px 100%; background-repeat: repeat no-repeat;"><p style="font-family: arial, nsimsun, sans-serif; margin: 0px; padding: 0.3em 5px 0.7em; font-size: 0.76em;">POSIX 表示可移植操作系统接口（Portable Operating System Interface ，缩写为 POSIX 是为了读音更像 UNIX）。电气和电子工程师协会（Institute of Electrical and Electronics Engineers，IEEE）最初开发 POSIX 标准，是为了提高 UNIX 环境下应用程序的可移植性。具体的说 POSIX 是 IEEE 为要在各种 UNIX 操作系统上运行的软件定义 API 所规定的一系列互相关联的标准的总称，而 X 则表明其对 Unix API 的传承。Linux 基本上逐步实现了 POSIX 兼容，但并没有参加正式的 POSIX 认证。当前的 POSIX 文档分为三个部分：POSIX Kernel API，POSIX 命令和工具集，及 POSIX 一致性测试。Posix 线程（POSIX threads，又称 Pthreads）是负责 POSIX 的 IEEE 委员会开发的一套线程接口。</p></div></div><div style="margin: 0px 0px 1.2em; width: 530px;"><h2><a name="firstmajorhead">Linux 线程模型</a></h2><div style="background-image: url(http://1.www.s81c.com/i/v16/t/container-gradient.gif); border-bottom-color: #cccccc; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: #cccccc; border-left-style: solid; border-left-width: 1px; border-right-color: #cccccc; border-right-style: solid; border-right-width: 1px; background-position: 0px 100%; background-repeat: repeat no-repeat;"><p style="font-family: arial, nsimsun, sans-serif; margin: 0px; padding: 0.3em 5px 0.7em; font-size: 0.76em;">Linux 最初用的线程模型是 LinuxThread, 它不兼容 POSIX，而且存在一些性能问题，所以目前 Linux 摒弃了它，采用了基于 Pthreads 的 NPTL（Native POSIX Threads Library for Linux）模型， NPTL 修复了 LinuxThread 的许多缺点，并提供了更好的性能。</p><ul ibm-no-links"="" style="list-style-type: none; margin: 0px; padding: 4px 3px 4px 0px; font-size: 0.76em;"><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/" style="color: #996699;">Linux 线程实现机制分析</a></li><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/l-threading.html" style="color: #996699;">Linux 线程模型的比较：LinuxThreads 和 NPTL</a></li><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/l-nptl/index.html" style="color: #996699;">Linux 线程库性能测试与分析</a></li></ul><p ibm-back-to-top=""  ibm-no-print"="" style="font-family: arial, nsimsun, sans-serif; margin: 0px; padding: 5px; font-size: 0.76em; clear: both; text-align: right; height: 15px;"><a href="http://www.ibm.com/developerworks/cn/linux/theme/posix_thread/#ibm-pcon" style="color: #996699; display: inline; margin: 0px; padding: 0px 0px 0px 18px; text-decoration: initial; background-image: url(http://1.www.s81c.com/i/v16/icons/u_bold.gif); font-weight: bold; background-position: 0px -1px; background-repeat: no-repeat no-repeat;">回页首</a></p></div></div><div style="margin: 0px 0px 1.2em; width: 530px;"><h2><a name="secondmajorhead">POSIX 线程详解</a></h2><div style="background-image: url(http://1.www.s81c.com/i/v16/t/container-gradient.gif); border-bottom-color: #cccccc; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: #cccccc; border-left-style: solid; border-left-width: 1px; border-right-color: #cccccc; border-right-style: solid; border-right-width: 1px; background-position: 0px 100%; background-repeat: repeat no-repeat;"><p style="font-family: arial, nsimsun, sans-serif; margin: 0px; padding: 0.3em 5px 0.7em; font-size: 0.76em;">Daniel Robbins 从实例入手，逐步讲解 POSIX thread 编程技巧，有共享内存、互斥以及条件变量的运用。</p><ul ibm-no-links"="" style="list-style-type: none; margin: 0px; padding: 4px 3px 4px 0px; font-size: 0.76em;"><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerWorks/cn/linux/l-pthred/index.html" style="color: #996699;">pthreads 的基本用法 -- 介绍 POSIX 线程</a></li><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/thread/posix_thread1/" style="color: #996699;">POSIX 线程详解，第 1 部分：一种支持内存共享的简捷工具</a></li><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/thread/posix_thread2/" style="color: #996699;">POSIX 线程详解，第 2 部分：称作互斥对象的小玩意</a></li><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/thread/posix_thread3/" style="color: #996699;">POSIX 线程详解，第 3 部分：使用条件变量提高效率</a></li></ul><p ibm-back-to-top=""  ibm-no-print"="" style="font-family: arial, nsimsun, sans-serif; margin: 0px; padding: 5px; font-size: 0.76em; clear: both; text-align: right; height: 15px;"><a href="http://www.ibm.com/developerworks/cn/linux/theme/posix_thread/#ibm-pcon" style="color: #996699; display: inline; margin: 0px; padding: 0px 0px 0px 18px; text-decoration: initial; background-image: url(http://1.www.s81c.com/i/v16/icons/u_bold.gif); font-weight: bold; background-position: 0px -1px; background-repeat: no-repeat no-repeat;">回页首</a></p></div></div><div style="margin: 0px 0px 1.2em; width: 530px;"><h2><a name="thirdmajorhead">Posix 线程编程指南</a></h2><div style="background-image: url(http://1.www.s81c.com/i/v16/t/container-gradient.gif); border-bottom-color: #cccccc; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: #cccccc; border-left-style: solid; border-left-width: 1px; border-right-color: #cccccc; border-right-style: solid; border-right-width: 1px; background-position: 0px 100%; background-repeat: repeat no-repeat;"><p style="font-family: arial, nsimsun, sans-serif; margin: 0px; padding: 0.3em 5px 0.7em; font-size: 0.76em;">本系列文章在阐明概念的基础上，向您详细地讲述了 Posix 线程库 API。</p><ul ibm-no-links"="" style="list-style-type: none; margin: 0px; padding: 4px 3px 4px 0px; font-size: 0.76em;"><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part1/" style="color: #996699;">Posix 线程编程指南，第 1 部分：线程创建与取消</a></li><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part2/" style="color: #996699;">Posix 线程编程指南，第 2 部分：线程私有数据</a></li><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part3/" style="color: #996699;">Posix 线程编程指南，第 3 部分：线程同步</a></li><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part4/" style="color: #996699;">Posix 线程编程指南，第 4 部分：线程终止</a></li><li style="font-family: arial, nsimsun, sans-serif; background-image: url(http://1.www.s81c.com/i/v16/bullets/sprites.gif); line-height: 1.2em; padding: 2px 2px 2px 14px; height: 14px; clear: left; background-position: 6px 0.15em; background-repeat: no-repeat no-repeat;"><a href="http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part5/" style="color: #996699;">Posix 线程编程指南，第 5 部分：杂项</a></li></ul><p ibm-back-to-top=""  ibm-no-print"="" style="font-family: arial, nsimsun, sans-serif; margin: 0px; padding: 5px; font-size: 0.76em; clear: both; text-align: right; height: 15px;"><a href="http://www.ibm.com/developerworks/cn/linux/theme/posix_thread/#ibm-pcon" style="color: #996699; display: inline; margin: 0px; padding: 0px 0px 0px 18px; text-decoration: initial; background-image: url(http://1.www.s81c.com/i/v16/icons/u_bold.gif); font-weight: bold; background-position: 0px -1px; background-repeat: no-repeat no-repeat;">回页首</a></p></div></div></div></div><img src ="http://www.cppblog.com/doing5552/aggbug/196877.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/doing5552/" target="_blank">doing5552</a> 2012-12-31 16:06 <a href="http://www.cppblog.com/doing5552/archive/2012/12/31/196877.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]正则表达式30分钟入门教程</title><link>http://www.cppblog.com/doing5552/archive/2012/11/09/194962.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Fri, 09 Nov 2012 02:35:00 GMT</pubDate><guid>http://www.cppblog.com/doing5552/archive/2012/11/09/194962.html</guid><wfw:comment>http://www.cppblog.com/doing5552/comments/194962.html</wfw:comment><comments>http://www.cppblog.com/doing5552/archive/2012/11/09/194962.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/doing5552/comments/commentRss/194962.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/doing5552/services/trackbacks/194962.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 版本：v2.32 (2011-8-17) 作者：deerchao&nbsp;转载请注明来源目录跳过目录本文目标如何使用本教程正则表达式到底是什么东西？入门测试正则表达式元字符字符转义重复字符类分枝条件反义分组后向引用零宽断言负向零宽断言注释贪婪与懒惰处理选项平衡组/递归匹配还有些什么东西没提到联系作者网上的资源及本文参考文献更新纪录本文目标30分钟内让你明白正则表达式是什么，并对它有一些基本的了解...&nbsp;&nbsp;<a href='http://www.cppblog.com/doing5552/archive/2012/11/09/194962.html'>阅读全文</a><img src ="http://www.cppblog.com/doing5552/aggbug/194962.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/doing5552/" target="_blank">doing5552</a> 2012-11-09 10:35 <a href="http://www.cppblog.com/doing5552/archive/2012/11/09/194962.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>工作二年</title><link>http://www.cppblog.com/doing5552/archive/2012/07/03/181275.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Tue, 03 Jul 2012 09:58:00 GMT</pubDate><guid>http://www.cppblog.com/doing5552/archive/2012/07/03/181275.html</guid><wfw:comment>http://www.cppblog.com/doing5552/comments/181275.html</wfw:comment><comments>http://www.cppblog.com/doing5552/archive/2012/07/03/181275.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/doing5552/comments/commentRss/181275.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/doing5552/services/trackbacks/181275.html</trackback:ping><description><![CDATA[工作两年了，今天把这个博客再重拾起来。<br />微博有点他泛滥了<img src ="http://www.cppblog.com/doing5552/aggbug/181275.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/doing5552/" target="_blank">doing5552</a> 2012-07-03 17:58 <a href="http://www.cppblog.com/doing5552/archive/2012/07/03/181275.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[ubunt gcc stl] 使用库函数 sort() 排序自定义类时重载operator&lt;</title><link>http://www.cppblog.com/doing5552/archive/2011/02/15/140098.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Tue, 15 Feb 2011 09:32:00 GMT</pubDate><guid>http://www.cppblog.com/doing5552/archive/2011/02/15/140098.html</guid><wfw:comment>http://www.cppblog.com/doing5552/comments/140098.html</wfw:comment><comments>http://www.cppblog.com/doing5552/archive/2011/02/15/140098.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/doing5552/comments/commentRss/140098.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/doing5552/services/trackbacks/140098.html</trackback:ping><description><![CDATA[自定义类<br>class arc {<br>&#8230;&#8230;<br>bool operator&lt;(const arc&amp; b) const;<br><br>}<br><br>用容器如vector,deque存放arc对象，再其上使用stl的algrithms中的sort算法：<br>sort(arcVector.begin(),arcVector.end());<br><br>方法中需要使用&#8220;&lt;&#8221;作比较操作，故需要重载operator&lt;<br>简单重载 bool operator(arc&amp;);<br>很可能报错：<br>/usr/include/c++/4.2/bits/stl_algo.h:100: 错误： no match 为&#8216;operator&lt;&#8217;在&#8216;__b &lt; __c&#8217;<br>主要是缺少const的限定（两个都需要）。<br>否则有错：<br>/usr/include/c++/4.2/bits/stl_algo.h:91: 错误： 将&#8216;const arc&#8217;作为&#8216;bool arc::operator&lt;(const arc&amp;)&#8217;的&#8216;this&#8217;实参时丢弃了类型限定<br><br>分析知道linux中stl下对C＋＋的类型安全约束很强，const保证导入对象和自身对象都不能被修改。<br>而stl的sort操作确实不需要修改比较的对象，也不应该被修改，故强制使用的自定义operator&lt;需要两个const限制比较的两个对象。<br><br>使用friend方法：<br>friend bool operator&lt;(const arc&amp;, const arc&amp;);<br><br>两种错误：<br>1.friend bool operator&lt;(const arc&amp;, const arc&amp;) const;<br>错误： non-成员函数&#8216;bool operator&lt;(const arc&amp;, const arc&amp;)&#8217;不能拥有 cv 限定符<br><br>2.bool operator&lt;(const arc&amp;, const arc&amp;) [const]<br>错误： &#8216;bool arc::operator&lt;(const arc&amp;, const arc&amp;) const&#8217;带且仅带 1 个实参
<img src ="http://www.cppblog.com/doing5552/aggbug/140098.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/doing5552/" target="_blank">doing5552</a> 2011-02-15 17:32 <a href="http://www.cppblog.com/doing5552/archive/2011/02/15/140098.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux Grep 用法</title><link>http://www.cppblog.com/doing5552/archive/2010/11/01/132025.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Mon, 01 Nov 2010 11:08:00 GMT</pubDate><guid>http://www.cppblog.com/doing5552/archive/2010/11/01/132025.html</guid><wfw:comment>http://www.cppblog.com/doing5552/comments/132025.html</wfw:comment><comments>http://www.cppblog.com/doing5552/archive/2010/11/01/132025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/doing5552/comments/commentRss/132025.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/doing5552/services/trackbacks/132025.html</trackback:ping><description><![CDATA[<div class=tit>c2008-04-02 09:12</div>
<table style="TABLE-LAYOUT: fixed; WIDTH: 100%">
    <tbody>
        <tr>
            <td>
            <div class=cnt id=blog_text>Grep : g (globally) search for a re (regular expression ) and p (print ) the results. <br><br>1、参数： <br>-I ：忽略大小写 <br>-c ：打印匹配的行数 <br>-l ：从多个文件中查找包含匹配项 <br>-v ：查找不包含匹配项的行 <br>-n：打印包含匹配项的行和行标 <br><br>2、RE（正则表达式） <br>\ 忽略正则表达式中特殊字符的原有含义 <br>^ 匹配正则表达式的开始行 <br>$ 匹配正则表达式的结束行 <br>\&lt; 从匹配正则表达式的行开始 <br>\&gt;; 到匹配正则表达式的行结束 <br>[ ] 单个字符；如[A] 即A符合要求 <br>[ - ] 范围 ；如[A-Z]即A，B，C一直到Z都符合要求 <br>. 所有的单个字符 <br>* 所有字符，长度可以为0 <br><br>3、举例 <br># ps -ef | grep in.telnetd <br>root 19955 181 0 13:43:53 ? 0:00 in.telnetd <br><br># more size.txt size文件的内容 <br>b124230 <br>b034325 <br>a081016 <br>m7187998 <br>m7282064 <br>a022021 <br>a061048 <br>m9324822 <br>b103303 <br>a013386 <br>b044525 <br>m8987131 <br>B081016 <br>M45678 <br>B103303 <br>BADc2345 <br><br># more size.txt | grep '[a-b]' 范围 ；如[A-Z]即A，B，C一直到Z都符合要求 <br>b124230 <br>b034325 <br>a081016 <br>a022021 <br>a061048 <br>b103303 <br>a013386 <br>b044525 <br># more size.txt | grep '[a-b]'* <br>b124230 <br>b034325 <br>a081016 <br>m7187998 <br>m7282064 <br>a022021 <br>a061048 <br>m9324822 <br>b103303 <br>a013386 <br>b044525 <br>m8987131 <br>B081016 <br>M45678 <br>B103303 <br>BADc2345 <br><br># more size.txt | grep '' 单个字符；如[A] 即A符合要求 <br>b124230 <br>b034325 <br>b103303 <br>b044525 <br># more size.txt | grep '[bB]' <br>b124230 <br>b034325 <br>b103303 <br>b044525 <br>B081016 <br>B103303 <br>BADc2345 <br><br># grep 'root' /etc/group <br>root::0:root <br>bin::2:root,bin,daemon <br>sys::3:root,bin,sys,adm <br>adm::4:root,adm,daemon <br>uucp::5:root,uucp <br>mail::6:root <br>tty::7:root,tty,adm <br>lp::8:root,lp,adm <br>nuucp::9:root,nuucp <br>daemon::12:root,daemon <br><br># grep '^root' /etc/group 匹配正则表达式的开始行 <br>root::0:root <br><br><br># grep 'uucp' /etc/group <br>uucp::5:root,uucp <br>nuucp::9:root,nuucp <br><br># grep '\&lt;uucp' /etc/group <br>uucp::5:root,uucp <br><br><br># grep 'root$' /etc/group 匹配正则表达式的结束行 <br>root::0:root <br>mail::6:root <br><br><br># more size.txt | grep -i 'b1..*3' -i ：忽略大小写 <br><br>b124230 <br>b103303 <br>B103303 <br><br># more size.txt | grep -iv 'b1..*3' -v ：查找不包含匹配项的行 <br><br>b034325 <br>a081016 <br>m7187998 <br>m7282064 <br>a022021 <br>a061048 <br>m9324822 <br>a013386 <br>b044525 <br>m8987131 <br>B081016 <br>M45678 <br>BADc2345 <br><br># more size.txt | grep -in 'b1..*3' <br>1:b124230 <br>9:b103303 <br>15:B103303 <br><br># grep '$' /etc/init.d/nfs.server | wc -l <br>128 <br># grep '\$' /etc/init.d/nfs.server | wc &#8211;l 忽略正则表达式中特殊字符的原有含义 <br><br>15 <br># grep '\$' /etc/init.d/nfs.server <br>case "$1" in <br>&gt;;/tmp/sharetab.$$ <br>[ "x$fstype" != xnfs ] &amp;&amp; \ <br>echo "$path\t$res\t$fstype\t$opts\t$desc" \ <br>&gt;;&gt;;/tmp/sharetab.$$ <br>/usr/bin/touch -r /etc/dfs/sharetab /tmp/sharetab.$$ <br>/usr/bin/mv -f /tmp/sharetab.$$ /etc/dfs/sharetab <br>if [ -f /etc/dfs/dfstab ] &amp;&amp; /usr/bin/egrep -v '^[ ]*(#|$)' \ <br>if [ $startnfsd -eq 0 -a -f /etc/rmmount.conf ] &amp;&amp; \ <br>if [ $startnfsd -ne 0 ]; then <br>elif [ ! -n "$_INIT_RUN_LEVEL" ]; then <br>while [ $wtime -gt 0 ]; do <br>wtime=`expr $wtime - 1` <br>if [ $wtime -eq 0 ]; then <br>echo "Usage: $0 { start | stop }" <br><br><br># more size.txt <br><br>the test file <br>their are files <br>The end <br><br># grep 'the' size.txt <br>the test file <br>their are files <br><br># grep '\&lt;the' size.txt <br>the test file <br>their are files <br><br># grep 'the\&gt;;' size.txt <br>the test file <br><br># grep '\&lt;the\&gt;;' size.txt <br>the test file <br><br># grep '\&lt;[Tt]he\&gt;;' size.txt <br>the test file <br>The end</div>
            </td>
        </tr>
    </tbody>
</table>
<br>
<img src ="http://www.cppblog.com/doing5552/aggbug/132025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/doing5552/" target="_blank">doing5552</a> 2010-11-01 19:08 <a href="http://www.cppblog.com/doing5552/archive/2010/11/01/132025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HTTP代理如何正确处理Cookie</title><link>http://www.cppblog.com/doing5552/archive/2010/10/10/129374.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Sun, 10 Oct 2010 14:29:00 GMT</pubDate><guid>http://www.cppblog.com/doing5552/archive/2010/10/10/129374.html</guid><wfw:comment>http://www.cppblog.com/doing5552/comments/129374.html</wfw:comment><comments>http://www.cppblog.com/doing5552/archive/2010/10/10/129374.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/doing5552/comments/commentRss/129374.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/doing5552/services/trackbacks/129374.html</trackback:ping><description><![CDATA[<p>2005 年 11 月 10 日</p>
<blockquote>大多数的 Web 应用程序都要求维护某种会话状态，如用户购物车的内容。这种会话状态的保持很多情况下需要借助于Cookie或者Session的帮助。本文结合在线页面翻译 （Machine Translation System）项目中对于Cookie的处理方法，探讨一下如何在HTTP应用代理中正确处理Cookie的传递和管理问题。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p>读者定位为具有Java和Web开发经验的开发和设计人员。</p>
<p>读者可以学习到关于Cookie的工作原理和Cookie协议的细节，以及在一个HTTP应用代理的场景下Cookie的管理和处理思想，并可以直接使用文中的代码和思路，提高工作效率。</p>
<p>随着越来越多的系统移植到了Web上，HTTP协议具有了比以前更广泛的应用。不同的系统对WEB实现提出了不同的要求，基于HTTP协议的网络应用正趋于复杂化和多元化。很多应用需要把用户请求的页面进行处理后再返回给用户，比如页面关键字过滤，页面内容缓存、内容搜索、页面翻译等等。这些应用在实际效果上类似于一个HTTP应用代理：它们首先接受用户的请求，根据用户请求的URL去真正的目标服务器取回目标页面，再根据不同应用的要求做出相应处理后返回给用户。这样用户直接面对的就是这个HTTP应用代理，而通过它与其他页面进行交互。Cookie或Session技术的应用，解决了HTTP协议的一个问题 -- 无法保持客户状态，因此它现在被广泛应用于各种Web站点中。上面提到的那些应用如果不能处理好Cookie和Session的传递、更新和废除等问题，就会极大的限制它们所能处理站点的范围，因此如何在HTTP应用代理中正确处理Cookie，成为一个必须解决的问题。本文结合在页面翻译（Machine Translation System）项目中对于Cookie的处理方法，探讨一下这方面的解决方案。</p>
<p><a name=N10047><span class=atitle>MTS项目简介及讨论前提</span></a></p>
<p>Machine Translation System（以下简称MTS）是一个在线实时页面翻译系统，为用户在线提供把英文页面翻译成其他9种语言的服务。用户通过向MTS系统提交一个类似下面的URL使用此服务，其中参数url指明了用户所需要翻译的目标地址，参数language指明了所需翻译成的目标语言，www.mts.com是假想中提供MTS服务的站点。</p>
<p><a href="http://www.mts.com/translate?url=http://www.ibm.com/&amp;language=French"><u><font color=#5c81a7>HTTP://www.mts.com/translate?url=http://www.ibm.com/&amp;language=French</font></u></a></p>
<p>一个完整的MTS系统处理过程可以分解成以下几个步骤：</p>
<ul>
    <li>用户向MTS提交合适的URL。
    <li>MTS在接到用户的请求后，解析出用户需要翻译的目标地址和目标语言，根据用户请求的目标地址，把请求转发到目标服务器。
    <li>MTS接受来自目标服务器的应答，包括页面信息和HTTP头信息。
    <li>MTS在确定得到正确的目标页面后，把页面内容送入WebSphere Translation Server进行翻译。
    <li>把翻译后的页面连同修改后的HTTP头信息提交给用户。 </li>
</ul>
<br><a name=N1006C><strong>MTS逻辑图</strong></a><br><img height=103 alt=MTS逻辑图 src="http://www.ibm.com/developerworks/cn/java/j-cookie/images/image002.jpg" width=359 border=0> <br>
<p>当然，这其中涉及到很多的应用处理。比如与各种HTTP/HTTPS站点建立联结、根据HTTP头信息进行页面跳转和错误处理、为始终保持用户在翻译模式下而对目标的HTML页面进行分析和修改，根据系统设置对某些DNT（Do Not Translate）的页面进行过滤和跳转，当然还有对Cookie的处理等等。其他问题跟这篇文章关联不大，我们重点讨论在这种情况下的Cookie处理。Cookie跟随目标服务器的HTTP头信息被MTS接收到，经过MTS整理之后发给客户端浏览器。MTS在接到下一次用户对同一个站点的翻译请求时，再把从客户端得到的Cookie发送给目标服务器。</p>
<p>在以上的场景中，MTS充当的作用类似于一种HTTP应用代理服务器，它代替用户取得目标页面，并在作出相应处理后再提交给用户。当然，这种代理服务器不需要用户修改浏览器的代理服务器参数或者网络配置，而只是简单的在浏览器的地址栏中输入一个MTS能够识别的URL即可。此篇文章也是在这样一个应用场景的基础上，展开对HTTP应用代理服务器如何处理Cookie的讨论。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="42" sizcache="2">
    <tbody sizset="42" sizcache="1">
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right sizset="43" sizcache="2">
    <tbody sizset="44" sizcache="2">
        <tr align=right sizset="44" sizcache="2">
            <td sizset="44" sizcache="2"><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0 sizset="44" sizcache="2">
                <tbody sizset="44" sizcache="1">
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/j-cookie/#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=N10082><span class=atitle>问题的产生</span></a></p>
<p>在MTS系统中，目标服务器的Cookie在两个地方会产生问题。当MTS接收目标服务器应答的时候，Cookie随着HTTP头信息被MTS接收到的。这时候目标服务器认为MTS就是最终客户，因此它赋予了Cookie与目标服务器相符的属性。而如果MTS把这些Cookie原封不动的保存在HTTP头信息中，传给真正的最终用户的话，用户的浏览器会因为这些Cookie不合法而忽略它们。同理，当Cookie从浏览器端传回目标服务器的时候，也会遇到相同的问题。因此有必要对Cookie进行一些处理，以保证用户的浏览器能真正识别和利用这些Cookie。</p>
<p>但是为何用户浏览器无法识别从目标服务器传过来的原始Cookie呢？这是因为出于安全性的考虑，Cookie规范制定的时候对Cookie的产生和接受设置了一些严格的规范，不符合这些规范的Cookie，浏览器和服务器都将予以忽略。下面我们从Cookie规范入手进行介绍。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="45" sizcache="2">
    <tbody sizset="45" sizcache="1">
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right sizset="46" sizcache="2">
    <tbody sizset="47" sizcache="2">
        <tr align=right sizset="47" sizcache="2">
            <td sizset="47" sizcache="2"><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0 sizset="47" sizcache="2">
                <tbody sizset="47" sizcache="1">
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/j-cookie/#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=N1008E><span class=atitle>Cookie的规范介绍</span></a></p>
<p>目前有以下几种Cookie规范：</p>
<ul>
    <li>Netscape cookie草案：是最早的cookie规范，基于rfc2109。尽管这个规范与rc2109有较大的差别，但是很多服务器都与之兼容。
    <li>rfc2109， 是w3c发布的第一个官方cookie规范。理论上讲，所有的服务器在处理cookie(版本1)时，都要遵循此规范。遗憾的是，这个规范太严格了，以致很多服务器不正确的实施了该规范或仍在使用Netscape规范。
    <li>rfc2965规范定义了cookie版本2，并说明了cookie版本1的不足。 </li>
</ul>
<p>rfc2965规范的使用，目前并不多。rfc2109规范相应要严格得多，在实际应用上，并不是所有的浏览器和Web服务器都严格遵守。因此相比较而言，Netscape cookie草案倒是一个比较简洁和被广泛支持的Cookie规范，因此我们在这里以Netscape cookie草案为基础进行讨论，对于其他两种规范，我们的讨论和代码具有相同的意义。关于Netscape cookie草案的细节，大家可以参照Netscape官方站点，这里我们列举一些和我们讨论有关的内容。</p>
<p>根据Netscape cookie草案的描述，Cookie 是Web 服务器向用户的浏览器发送的一段ASCII码文本。一旦收到Cookie，浏览器会把Cookie的信息片断以"名/值"对(name-value pairs)的形式储存保存在本地。这以后，每当向同一个Web 服务器请求一个新的文档时，Web 浏览器都会发送之站点以前存储在本地的Cookie。创建Cookie的最初目的是想让Web服务器能够通过多个HTTP请求追踪客户。有些复杂的网络应用需要在不同的网页之间保持一致，它们需要这种会话状态的保持能力。</p>
<p>浏览器与Web服务器通过HTTP协议进行通讯，而Cookie就是保存在HTTP协议的请求或者应答头部（在HTTP协议中，数据包括两部分，一部分是头部，由一些名值对构成，用来描述要被传输数据的一些信息。一部分是主体(body)，是真正的数据（如HTML页面等））进行传送的。</p>
<p>在HTML文档被发送之前，Web服务器通过传送HTTP 包头中的Set-Cookie 消息把一个cookie 发送到用户的浏览器中。下面是一个遵循Netscape cookie草案的完整的Set-Cookie 头：</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="48" sizcache="2">
    <tbody sizset="48" sizcache="1">
        <tr>
            <td class=code-outline>
            <pre class=displaycode>Set-Cookie：customer=huangxp; path=/foo; domain=.ibm.com;
            expires= Wednesday, 19-OCT-05 23:12:40 GMT; [secure]
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>Set-Cookie的每个属性解释如下：</p>
<ul>
    <li>Customer=huangxp 一个"名称＝值"对，把名称customer设置为值"huangxp"，这个属性在Cookie中必须有。
    <li>path=/foo 控制哪些访问能够触发cookie 的发送。如果没有指定path，cookie 会在所有对此站点的HTTP 传送时发送。如果path=/directory，只有访问/directory 下面的网页时，cookie才被发送。在这个例子中，用户在访问目录/foo下的内容时，浏览器将发送此cookie。如果指定了path，但是path与当前访问的url不符，则此cookie将被忽略。
    <li>domain=.ibm.com 指定cookie被发送到哪台计算机上。正常情况下，cookie只被送回最初向用户发送cookie 的计算机。在这个例子中，cookie 会被发送到任何在.ibm.com域中的主机。如果domain 被设为空，domain 就被设置为和提供cookie 的Web 服务器相同。如果domain不为空，并且它的值又和提供cookie的Web服务器域名不符，这个Cookie将被忽略。
    <li>expires= Wednesday, 19-OCT-05 23:12:40 GMT 指定cookie 失效的时间。如果没有指定失效时间，这个cookie 就不会被写入计算机的硬盘上，并且只持续到这次会话结束。
    <li>secure 如果secure 这个词被作为Set-Cookie 头的一部分，那么cookie 只能通过安全通道传输（目前即SSL通道）。否则，浏览器将忽略此Cookie。 </li>
</ul>
<p>一旦浏览器接收了cookie，这个cookie和对远端Web服务器的连续请求将一起被浏览器发送。例如 前一个cookie 被存入浏览器并且浏览器试图请求 URL http://www.ibm.com/foo/index.html 时，下面的HTTP 包头就被发送到远端的Web服务器。</p>
<p>GET /foo/index.html HTTP/1.0<br>Cookie：customer=huangxp </p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="49" sizcache="2">
    <tbody sizset="49" sizcache="1">
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right sizset="50" sizcache="2">
    <tbody sizset="51" sizcache="2">
        <tr align=right sizset="51" sizcache="2">
            <td sizset="51" sizcache="2"><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0 sizset="51" sizcache="2">
                <tbody sizset="51" sizcache="1">
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/j-cookie/#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=N100D5><span class=atitle>一次典型的网络浏览过程</span></a></p>
<p>在了解了Cookie协议的一些基本内容之后，让我们看看一次典型的网络浏览过程中浏览器如何识别和处理Cookie：</p>
<ul>
    <li>浏览器对于Web服务器应答包头中Cookie的操作步骤：<br>1. 从Web服务器的应答包头中提取所有的cookie。<br>2. 解析这些cookie的组成部分（名称，值，路径等等）。<br>3. 判定主机是否允许设置这些cookie。允许的话，则把这些Cookie存储在本地。
    <li>浏览器对Web服务器请求包头中所有的Cookie进行筛选的步骤：<br>1. 根据请求的URL和本地存储cookie的属性，判断那些Cookie能被发送给Web服务器。<br>2. 对于多个cookie，判定发送的顺序。<br>3. 把需要发送的Cookie加入到请求HTTP包头中一起发送。 </li>
</ul>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="52" sizcache="2">
    <tbody sizset="52" sizcache="1">
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right sizset="53" sizcache="2">
    <tbody sizset="54" sizcache="2">
        <tr align=right sizset="54" sizcache="2">
            <td sizset="54" sizcache="2"><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0 sizset="54" sizcache="2">
                <tbody sizset="54" sizcache="1">
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/j-cookie/#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=N100F3><span class=atitle>由MTS代理的网络浏览过程</span></a></p>
<p>以上我们了解了在一个典型的浏览器与Web服务器交互的时候，Cookie的传递过程。下面我们将看到，如果在MTS代理网络浏览的过程中，不对Cookie进行修改，上面的Cookie传递过程将无法实现。</p>
<p>1. 假设用户希望把 http://www.ibm.com/foo/index.html 页面翻译成法文，应该使用如下的url对MTS发出请求</p>
：
<p>http://www.mts.com/translate?url=http://www.ibm.com/foo/index.html&amp;language=French</p>
<p>2. MTS接收用户的请求，连接远程目标服务器 http://www.ibm.com/foo/index.html。目标服务器做出应答，返回HTTP头和HTML页面内容。其中，典型的HTTP头内容如下：</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="55" sizcache="2">
    <tbody sizset="55" sizcache="1">
        <tr>
            <td class=code-outline>
            <pre class=displaycode>HTTP/1.1 200 OK
            Date: Mon, 24 Oct 2005 06:54:41 GMT
            Server: IBM_HTTP_Server
            Cache-Control: no-cache
            Content-Length: 19885
            Connection: close
            Set-Cookie：customer=huangxp; path=/foo; domain=.ibm.com;
            expires= Wednesday, 19-OCT-05 23:12:40 GMT
            Content-Type: text/html
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>3. MTS不对Set-Cookie后的内容作任何处理，直接把它加到用户浏览器的应答头上发送给浏览器。</p>
<p>4. 浏览器将从Set-Cookie中解析出domain和path的值，分别是.ibm.com和/foo，并与请求的url：http://www.mts.com/translate?url=http://www.ibm.com/foo/index.html&amp;language=French进行比较。请求url的domain是www.mts.com，path是/，与Set-Cookie中的属性不符，所以浏览器将忽略此Cookie。</p>
<p>另外，在浏览器发送Cookie的时候也会遇到同样的问题，同样如上例，如果浏览器里本来已经存储了http://www.ibm.com/foo/的Cookie，但由于用户要通过MTS访问此站点，浏览器经不会把已经存储的Cookie上转到MTS中，MTS也就无法把之传递到http://ibm.com/foo/上。</p>
<p>基于上面Cookie规范的介绍和例证，我们能看出，浏览器在接受某一个站点的Cookie的时候，需要检查Cookie的参数domain、path、secure，看是否与当前的站点和URL相符，如果不符的话，就会忽略。另一方面。浏览器在上传Cookie的时候，也会根据当前所访问站点的属性，上传相关的Cookie，而其他的Cookie则不予上传。</p>
<p>至此，我们讨论了需要修改Cookie的根本原因在于Cookie规范的限制。下面我们讨论两种解决问题的思路。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="56" sizcache="2">
    <tbody sizset="56" sizcache="1">
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right sizset="57" sizcache="2">
    <tbody sizset="58" sizcache="2">
        <tr align=right sizset="58" sizcache="2">
            <td sizset="58" sizcache="2"><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0 sizset="58" sizcache="2">
                <tbody sizset="58" sizcache="1">
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/j-cookie/#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=N1011D><span class=atitle>解决问题的两种思路</span></a></p>
<p>Cookie的存在是要解决HTTP协议本身先天的缺陷-无状态性，它为用户保存了一些需要的状态信息。因此我们解决此问题的最本质的出发点，也就是找到一种途径能为用户保存Cookie所提供用户状态信息，实际上就是Name/Value对。</p>
<p><a name=N10126><span class=smalltitle><strong><font face=Arial>思路一</font></strong></span></a></p>
<p>第一种思路就是修改目标服务器取得的Cookie，使之符合MTS站点的属性，然后作为MTS站点的Cookie存储到用户的浏览器中去。当然，这种修改必须保留原始Cookie的所有属性值，当以后访问同一个目标服务器的时候，MTS能根据保存的属性值还原出原始Cookie，然后进行提交。</p>
<p>具体到属性值的保存位置，没有太多选择的余地，实际上，domain，path，secure，expires这几个属性都无法利用，只有利用name=value这一属性对。我们的做法是创造一个新的Cookie，把原始Cookie的domain，path的值与name值进行编码，用分隔符附加在Name值的后面，符值给新的Cookie。这样做也同时避免了不同目标服务器如果出现同名的Cookie，将会互相覆盖的情况（Cookie规范里面也规定了，客户端以domain，path，name作为Cookie的唯一标示）。而原始Cookie的secure和expires值，直接符给新的Cookie，新Cookie的domain和path设成缺省值，这样，新Cookie就可以被浏览器正常接受。由于浏览器接受的所有Cookie的domain和path值都一样，因此每次用户对MTS提出请求时，浏览器都会把所有与MTS站点相关的Cookie上传，因此，MTS还需要还原原始的Cookie，过滤掉与目标服务器不相干的Cookie，然后上传有用的Cookie。</p>
<p>这种思路的优点在于Cookie存储在客户端，可以做到长期存储，浏览器自己根据Cookie的expires值做出判断，省掉很多开发的麻烦。缺点是转换的过程相对较复杂。另外还有一个缺点，也是由于Cookie规范的限制所造成的。Cookie规范对于一个浏览器同时能够存储的Cookie数量作出了规定。</p>
<ul>
    <li>总共300 个cookie
    <li>每个Cookie 4 K 的存储容量
    <li>每一个domain 或者 server 20 个cookie。 </li>
</ul>
<p>以上是浏览器所应达到的最小存储数量，超出这个限制，浏览器应该自动按照最少最近被使用的原则删除超出得Cookie。由于用户有可能通过MTS这一个网站翻译大量的目标服务器，因此浏览器存储在MTS的domain下的cookie数量就很有可能超过20个，这时候就会导致某些Cookie被删除。一般这也不会造成太大问题，因为规范是要求浏览器删除最少最近被使用的Cookie，但我们在实际测试当中发现有些浏览器并不遵守这样的规范，而是删除最新的Cookie，这就将导致用户很大的不便。</p>
<p><a name=N10144><span class=smalltitle><strong><font face=Arial>思路二</font></strong></span></a></p>
<p>第二种思路在于把原始的Cookie组织成dataBean，存储到用户的Session当中去。这样，在用户端只需要存储一个SessionID的Cookie，而不需要存储所有目标服务器的每一个Cookie。另外，当接收到用户的又一次翻译请求时，再从Session当中取出所有的dataBean，逐一进行分析，找出与用户所请求的目标服务器相符的原始Cookie，进行提交。</p>
<p>这种思路可以克服上一种思路中Cookie超过标准数量时的缺陷，而且不需编码保存原始的Cookie属性值，减少了程序的复杂度。缺点是需要程序员自己处理expires。而且由于是把Cookie存储在Session中，一旦Session失效，所有Cookie都将被删除，所以，无法保存那些长期的Cookie。</p>
<p>总之，两种思路各有利弊，在实际应用当中要权衡考虑。下面我们针对两种思路进行技术实现，分别对应方案一和方案二。</p>
<p>由于MTS需要与目标服务器连接，遵循HTTP协议读取和返回Cookie，但是如果用JDK中的java.net.URLConnection处理Cookie将非常不方便，因此我们使用HTTPClient来处理与目标服务器的连接。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="59" sizcache="2">
    <tbody sizset="59" sizcache="1">
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right sizset="60" sizcache="2">
    <tbody sizset="61" sizcache="2">
        <tr align=right sizset="61" sizcache="2">
            <td sizset="61" sizcache="2"><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0 sizset="61" sizcache="2">
                <tbody sizset="61" sizcache="1">
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/j-cookie/#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=N10156><span class=atitle>方案一：Cookie存储在浏览器端</span></a></p>
<p>用户每发起一次新的请求，浏览器在检查完本地存储Cookie的有效性后，会把所有由MTS产生的有效Cookie附加在请求头里送到MTS。MTS接受到客户端的翻译请求后，从Request中提取出所有的Cookie，还原后根据目标服务器的domain和path进行过滤。产生所有与目标服务器相关的Cookie。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="62" sizcache="2">
    <tbody sizset="62" sizcache="1">
        <tr>
            <td class=code-outline>
            <pre class=displaycode>//从request中获取所有的Cookie
            javax.servlet.http.Cookie[] theCookies = request.getCookies();
            ArrayList cookiesList = new ArrayList();
            String url = request.getParameter("url");
            String domain = URLUtil.getURLHost(url);
            String path = URLUtil.getPath(url);
            if (theCookies != null)
            {
            for (int i = 0; i &lt; theCookies.length; i++)
            {
            RE r = new RE();
            //用正则表达式把name项还原成domain，path，name
            REDebugCompiler compiler = new REDebugCompiler();
            r.setProgram(compiler.compile("\\|\\|"));
            String[] values = r.split(theCookies[i].getName());
            //"9.181.116.183||/MTModule||testCookie:value1" or " ||
            ||testCookie:value1"
            if (values.length == 3)
            {
            if (values[0].trim().startsWith("."))
            {
            if (!domain.endsWith(values[0].trim()))
            continue;
            } else if (!domain.endsWith("://" + values[0].trim()))
            continue;
            if (!path.startsWith(values[1].trim()))
            continue;
            Cookie tempCookie = new Cookie();
            tempCookie.setDomain(
            ("".equals(values[0].trim())) ? null : values[0]);
            tempCookie.setPath(
            ("".equals(values[1].trim())) ? null : values[1]);
            tempCookie.setName(
            ("".equals(values[2].trim())) ? null : values[2]);
            tempCookie.setSecure(theCookies[i].getSecure());
            tempCookie.setValue(theCookies[i].getValue());
            tempCookie.setVersion(theCookies[i].getVersion());
            tempCookie.setComment(theCookies[i].getComment());
            cookiesList.add(tempCookie);
            }
            }
            }
            //transferedCookie用来存储将被传到目标服务器的Cookie
            Cookie[] transferedCookie = new Cookie[cookiesList.size()];
            cookiesList.toArray(transferedCookie);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>接下来，需要把Cookie送到目标服务器中。我们使用HTTPClient与目标服务器连接。HTTPClient在与目标服务器连接以后，允许服务器设置Cookie并在需要的时候自动将Cookie返回服务器，也支持手工设置 Cookie后发送到服务器端。但是，由于如何处理cookie有几个规范互相冲突：Netscape Cookie 草案、RFC2109、RFC2965，而且还有很大数量的软件商的Cookie实现不遵循任何规范。 为了处理这种状况，需要把HttpClient设置成Cookie兼容模式，这样可以最大限度的处理好各种Cookie。下面的代码把Cookie送到目标服务器。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="63" sizcache="2">
    <tbody sizset="63" sizcache="1">
        <tr>
            <td class=code-outline>
            <pre class=displaycode>HttpClient client = new HttpClient();
            //从request得到所有需要传输的cookie
            Cookie[] questCookie = getCookieFromRequest(request);
            //设置HTTPClient为Cookie兼容模式
            client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);
            if (questCookie.length &gt; 0)
            //把Cookie加到httpclient中
            client.getState().addCookies(questCookie);
            HttpMethod method = new GetMethod(TagerURL);
            //向目标服务器发送请求
            int statusCode = client.executeMethod(method);
            method.releaseConnection();
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>MTS把请求和Cookie送出后，继续接收目标服务器的应答，读取返回的原始Cookie，并转换成可以存储在用户浏览器端的Cookie。下面的代码将对原始Cookie的内容进行变换，保留expires和secure等项，把domain和path项编码到name中去。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="64" sizcache="2">
    <tbody sizset="64" sizcache="1">
        <tr>
            <td class=code-outline>
            <pre class=displaycode>//从HTTPClient中取得所有的Cookie
            Cookie[] temp = client.getState().getCookies();
            if (temp != null)
            {
            javax.servlet.httpCookie theCookie = new javax.servlet.http.Cookie[temp.length];
            //逐一对Cookie进行处理
            for (int i = 0; i &lt; temp.length; i++)
            {    StringBuffer sb = new StringBuffer();
            //编码成domain||path||name
            sb.append(
            temp[i].getDomain() == null ? " " : temp[i].getDomain());
            sb.append("||");
            sb.append(temp[i].getPath() == null ? " " : temp[i].getPath());
            sb.append("||");
            sb.append(temp[i].getName() == null ? " " : temp[i].getName());
            theCookie[i] =
            new Cookie(sb.toString(),temp[i].getValue());
            //复制其他项
            theCookie[i].setMaxAge(theCookie[i].getMaxAge();
            theCookie[i].setSecure(temp[i].getSecure());
            theCookie[i].setVersion(temp[i].getVersion());
            theCookie[i].setComment(temp[i].getComment());
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>最后一步，把这些Cookie保存到response里，随HTTP应答头返回用户浏览器。并保存在浏览器中。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="65" sizcache="2">
    <tbody sizset="65" sizcache="1">
        <tr>
            <td class=code-outline>
            <pre class=displaycode>//把所有转换后的Cookie加入response
            for (int i = 0; i &lt; theCookie.length; i++) {
            response.addCookie(theCookie[i]);
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>至此，我们已经完成了接收用户请求，转换Cookie，发送到目标服务器，接收目标服务器的原始Cookie，并保存在客户浏览器的整个处理过程。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="66" sizcache="2">
    <tbody sizset="66" sizcache="1">
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right sizset="67" sizcache="2">
    <tbody sizset="68" sizcache="2">
        <tr align=right sizset="68" sizcache="2">
            <td sizset="68" sizcache="2"><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0 sizset="68" sizcache="2">
                <tbody sizset="68" sizcache="1">
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/j-cookie/#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=N1018F><span class=atitle>方案二：Cookie存储在服务器端</span></a></p>
<p>在此种方案中，目标服务器返回给MTS的Cookie将被组织成dataBean，存储在用户的Session中。因此，我们首先生成一个用来存储Cookie的类CookiesBean，根据它的特性，它可以继承ArraryList类。此对象将存储用户访问目标服务器时接收到的所有Cookie，并提供与新接收到的Cookie融合的功能，同时能够删除过期的Cookie，更新同名的Cookie。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="69" sizcache="2">
    <tbody sizset="69" sizcache="1">
        <tr>
            <td class=code-outline>
            <pre class=displaycode>public class CookiesBean extends ArrayList
            {
            /**
            * 处理Cookies.
            * @参数 Cookies array
            */
            public CookiesBean(Cookie[] cook)
            {
            if (cook == null)
            return;
            //add all cookie which isn't expired.
            for (int i = 0; i &lt; cook.length; i++)
            {
            if (!cook[i].isExpired())
            {
            add(cook[i]);
            }
            }
            }
            /**
            * 融合参数中的bean
            * @参数 bean
            * 参考: rfc2109 4.3.3  Cookie Management
            */
            public void RefreshBean(CookiesBean bean)
            {
            if (bean == null)
            return;
            Iterator it = bean.iterator();
            //针对bean中的每一个Cookie进行处理
            while (it.hasNext())
            {
            Cookie beanCookie = (Cookie) it.next();
            if (beanCookie == null) continue;
            ArrayList drop = new ArrayList();
            Iterator thisIt = iterator();
            //取出存储的Cookie进行比较和处理
            while (thisIt.hasNext())
            {
            Cookie thisCookie = (Cookie) thisIt.next();
            if (thisCookie == null) continue;
            //比较name，domain和path,如果一样的话，则把此Cookie移到drop中
            if (CommonMethods
            .CompString(beanCookie.getName(), thisCookie.getName())
            <!-- code sample is too wide -->					&amp;&amp; CommonMethods.CompString(
            beanCookie.getDomain(),
            thisCookie.getDomain())
            &amp;&amp; CommonMethods.CompString(
            beanCookie.getPath(),
            thisCookie.getPath()))
            {
            drop.add(thisCookie);
            continue;
            }
            //删除过期的Cookie
            if (thisCookie.isExpired())
            drop.add(thisCookie);
            }
            //删除所有drop中的Cookie
            this.removeAll(drop);
            //如果beanCookie有效，则加入到存储区中。
            if (!beanCookie.isExpired())
            add(beanCookie);
            }
            return;
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>当MTS接受到客户端的翻译请求后，会从Session中提取出所有的dataBean，并得到存储的所有Cookie。如以下代码：</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="70" sizcache="2">
    <tbody sizset="70" sizcache="1">
        <tr>
            <td class=code-outline>
            <pre class=displaycode>				CookiesBean dataBean = null;
            Cookie[] theCookies = new Cookie[0];
            ArrayList cookiesList = new ArrayList();
            //获得Session，并获得dataBean
            HttpSession session = request.getSession(false);
            if (session != null)
            {
            dataBean = (CookiesBean) session.getAttribute(SESSION_NAME);
            }
            else
            {
            return theCookies;
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>MTS在所有的存储的Cookie中，检查Cookie的Domain、path和secure的值，筛选出符合目标服务器的Cookie。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="71" sizcache="2">
    <tbody sizset="71" sizcache="1">
        <tr>
            <td class=code-outline>
            <pre class=displaycode>				//提取目标服务器的domain和path
            String url = context.getURL();
            String domain = URLUtil.getURLHost(url);
            String path = url.substring(domain.length());
            String cookiedomain = null;
            String cookiepath = null;
            //逐个比较Cookie的domain和path
            //把符合要求的Cookie纪录到cookiesList中
            for (int i = 0; i &lt; dataBean.size(); i++)
            {
            Cookie cookie = (Cookie) dataBean.get(i);
            if (cookie == null) continue;
            cookiedomain =
            (cookie.getDomain() == null) ? "" : cookie.getDomain();
            cookiepath = (cookie.getPath() == null) ? "  " : cookie.getPath();
            if (!path.startsWith(cookiepath))
            continue;
            if (cookiedomain.startsWith("."))
            {
            if (!domain.endsWith(cookiedomain))
            continue;
            }
            else if (!domain.endsWith("://" + cookiedomain))
            continue;
            if (cookie.isExpired())
            continue;
            if (cookie.getSecure() &amp;&amp; url.toLowerCase().startsWith("http:"))
            continue;
            cookiesList.add(cookie);
            }
            theCookies = new Cookie[cookiesList.size()];
            cookiesList.toArray(theCookies);
            return theCookies;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>把Cookie送到目标服务器的代码与方案一基本一样，在此忽略。</p>
<p>最后一步，需要把Cookie存储到Session中。下面的代码将从目标服务器接受Cookie，融入到dataBean中，并保存到客户的Session中。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="72" sizcache="2">
    <tbody sizset="72" sizcache="1">
        <tr>
            <td class=code-outline>
            <pre class=displaycode>		//从目标服务器得到Cookie集
            Cookie[] cookies = client.getState().getCookies();
            CookiesBean bean = new CookiesBean(cookies);
            CookiesBean dataBean = bean;
            //取得用户Session
            HttpSession session =  request.getSession(false);
            if (session != null)
            {
            if (session.getAttribute(SESSION_NAME) != null)
            {
            //读取Session中存取的dataBean
            dataBean = (CookiesBean) session.getAttribute(SESSION_NAME);
            //目标服务器端的Cookie融合到Session中的dataBean中
            dataBean.RefreshBean(bean);
            }
            //把最终的dataBean存入Session中
            session.setAttribute(SESSION_NAME, dataBean);
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>至此，我们已经完成了在Session中保存个目标服务器所产生Cookie的整个处理过程。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="73" sizcache="2">
    <tbody sizset="73" sizcache="1">
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right sizset="74" sizcache="2">
    <tbody sizset="75" sizcache="2">
        <tr align=right sizset="75" sizcache="2">
            <td sizset="75" sizcache="2"><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0 sizset="75" sizcache="2">
                <tbody sizset="75" sizcache="1">
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/j-cookie/#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=N101CB><span class=atitle>关于Session的考虑</span></a></p>
<p>在研究完如何管理和传递Cookie之后，我们也需要研究一下Session的传递。因为目前大部分站点都在采用Session机制保存用户状态数据，如果不能解决Session的传递问题，HTTP应用代理服务器的适用范围同样会大打折扣。</p>
<p>首先我们了解一下Session的实现机制。Session是一种服务器端的机制，服务器使用一种类似于散列表的结构来保存信息。当程序需要为某个客户端的请求创建一个session的时候，服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id，如果已包含一个session id则说明以前已经为此客户端创建过session，服务器就按照session id把这个session检索出来使用（如果检索不到，可能会新建一个），session id的值应该是一个既不会重复，又不容易被找到规律以仿造的字符串。</p>
<p>保存这个session id的方式之一就是采用Cookie。一般这个Cookie的名字都类似于 SESSIONID。比如WebSphere对于Web应用程序生成的Cookie：JSESSIONID= 0001HWF4iVD94pY8Cpbx6U4CXkf:10lro0398，它的名字就是 JSESSIONID。</p>
<p>保存session id的其他方式还包括URL重写和表单隐藏字段。这两种方式都不需要代理服务器作特殊处理。因此实际上，我们解决了Cookie的管理和传递的问题之后，也就解决了Session的管理和传递。</p>
<br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="76" sizcache="2">
    <tbody sizset="76" sizcache="1">
        <tr>
            <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
        </tr>
    </tbody>
</table>
<table class=no-print cellSpacing=0 cellPadding=0 align=right sizset="77" sizcache="2">
    <tbody sizset="78" sizcache="2">
        <tr align=right sizset="78" sizcache="2">
            <td sizset="78" sizcache="2"><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
            <table cellSpacing=0 cellPadding=0 border=0 sizset="78" sizcache="2">
                <tbody sizset="78" sizcache="1">
                    <tr>
                        <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                        <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/java/j-cookie/#main"><strong><font color=#996699>回页首</font></strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<p><a name=N101DD><span class=atitle>结束语</span></a></p>
<p>从上面的讨论中可以看出，由于Cookie本身的规范限制，HTTP应用代理所必需面对的一个问题就是如何对Cookie进行正确的处理。本文对此提出了两种解决思路并列出了实现代码。对于MTS项目本身，我们使用的是第二种方案。开发人员在认识好Cookie本身的特性之后，参照本文的思路，根据自己系统的特点，也会找出更适宜的解决方案。</p>
<br><br>
<p><a name=resources><span class=atitle>参考资料 </span></a></p>
<ul>
    <li>Netscape Cookie Specification 对Netscape Cookie 使用的特性进行了简要的介绍。<br><br>
    <li>RFC2965：HTTP State Management Mechanism 介绍了HTTP 状态管理机制<br><br>
    <li>RFC2109 w3c发布的第一个官方cookie规范<br><br>
    <li>RFC2616：Hypertext Transfer Protocol 超文本传输协议<br><br>
    <li>Ronald Tschalr开发了 HTTPClient，将其作为 URLConnection 的替代品。<br><br>
    <li>Jakarta Regexp Apache 的开源项目，处理正则表达式的java包。<br></li>
</ul>
<br><br>
<p><a name=author><span class=atitle>关于作者</span></a></p>
<table cellSpacing=0 cellPadding=0 width="100%" border=0 sizset="79" sizcache="2">
    <tbody sizset="79" sizcache="1">
        <tr>
            <td colSpan=3><img height=5 alt="" src="http://www.ibm.com/i/c.gif" width="100%"></td>
        </tr>
        <tr vAlign=top align=left>
            <td>
            <p>&#160;</p>
            </td>
            <td><img height=5 alt="" src="http://www.ibm.com/i/c.gif" width=4></td>
            <td width="100%">
            <p>黄湘平是一名工作在IBM CSDL的高级软件工程师，从1997年开始从事网络开发设计工作。他对Java的网络和Web开发有丰富的经验，对底层协议也有一定的了解。现在正从事于页面在线翻译项目的开发和支持。你可以通过<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#106;&#111;&#98;&#105;&#107;&#101;&#64;&#115;&#105;&#110;&#97;&#46;&#99;&#111;&#109;&#63;&#99;&#99;&#61;"><u><font color=#5c81a7>jobike@sina.com</font></u></a>与黄湘平联系。</p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/doing5552/aggbug/129374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/doing5552/" target="_blank">doing5552</a> 2010-10-10 22:29 <a href="http://www.cppblog.com/doing5552/archive/2010/10/10/129374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转)指针的引用（*&amp;）与指针的指针（**）</title><link>http://www.cppblog.com/doing5552/archive/2010/09/28/127994.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Tue, 28 Sep 2010 14:06:00 GMT</pubDate><guid>http://www.cppblog.com/doing5552/archive/2010/09/28/127994.html</guid><wfw:comment>http://www.cppblog.com/doing5552/comments/127994.html</wfw:comment><comments>http://www.cppblog.com/doing5552/archive/2010/09/28/127994.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/doing5552/comments/commentRss/127994.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/doing5552/services/trackbacks/127994.html</trackback:ping><description><![CDATA[在下列函数声明中，为什么要<a class=vLink1 id=vad_8 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,8,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,8)" href="http://221.238.248.251/click/c1.php?r=http%3A//hiaurora.blogbus.com/logs/23641245.html&amp;aid=11695&amp;sid=6235007045041189&amp;click=1&amp;url=http%3A//www.ef.com.cn/englishfirst/quiz/default.aspx%3Fetag%3DEFCN_ParentQuiz_AFVogate001%20&amp;v=0&amp;k=%u540C%u65F6&amp;s=http%3A//www.programfan.com/article/2901.html&amp;rn=105230" target=_blank name=8>同时</a>使用*和&amp;符号？以及什么场合使用这种声明方式? <br>　　void func1（ MYCLASS *&amp;pBuildingElement ）； <br><br>　　论坛中经常有人问到这样的问题。本文试图<a class=vLink1 id=vad_4 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,4,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,4)" href="http://221.238.248.251/click/c1.php?r=http%3A//hiaurora.blogbus.com/logs/23641245.html&amp;aid=11696&amp;sid=6235007045041189&amp;click=1&amp;url=http%3A//www.ef.com.cn/englishfirst/landing/autumn10/default.aspx%3Fetag%3DEFCN_Autumn2010_AFVogate&amp;v=0&amp;k=%u901A%u8FC7&amp;s=http%3A//www.programfan.com/article/2901.html&amp;rn=580418" target=_blank name=4>通过</a>一些<a class=vLink1 id=vad_9 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,9,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,9)" href="http://221.238.248.251/click/c1.php?r=http%3A//hiaurora.blogbus.com/logs/23641245.html&amp;aid=11694&amp;sid=6235007045041189&amp;click=1&amp;url=http%3A//www.ef.com.cn/englishfirst/portal/default.aspx%3Fetag%3DEFCN_KidsDLP_AFVogate001&amp;v=0&amp;k=%u5B9E%u9645&amp;s=http%3A//www.programfan.com/article/2901.html&amp;rn=953382" target=_blank name=9>实际</a>的指针使用<a class=vLink1 id=vad_7 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,7,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,7)" href="http://221.238.248.251/click/c1.php?r=http%3A//hiaurora.blogbus.com/logs/23641245.html&amp;aid=11708&amp;sid=6235007045041189&amp;click=1&amp;url=http%3A//www.ef.com.cn/englishfirst/quiz/default.aspx%3Fetag%3DEFCN_ParentQuiz_AFVogate001%20&amp;v=0&amp;k=%u7ECF%u9A8C&amp;s=http%3A//www.programfan.com/article/2901.html&amp;rn=170401" target=_blank name=7>经验</a>来解释这个问题。<br>仔细看一下这种声明方式，确实有点让人迷惑。在某种意义上，"*"和"&amp;"是意思相对的两个东西，把它们放在一起有什么意义呢？。为了理解指针的这种做法，我们先复习一下C/C++编程中无所不在的指针概念。我们都知道MYCLASS*的意思：指向某个对象的指针，此对象的类型为MYCLASS。 Void func1（MYCLASS *pMyClass）； <br><br>// 例如： MYCLASS* p = new MYCLASS；<br>func1（p）； <br>上面这段代码的这种处理方法想必谁都用过，创建一个MYCLASS对象，然后将它传入func1函数。现在假设此函数要修改pMyClass： void func1（MYCLASS *pMyClass）<br>{<br>DoSomething（pMyClass）；<br>pMyClass = // 其它对象的指针<br>} <br><br>　　第二条语句在函数过程中只修改了pMyClass的值。并没有修改调用者的变量p的值。<a class=vLink1 id=vad_11 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,11,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,11)" href="http://221.238.248.251/click/c1.php?r=http%3A//hiaurora.blogbus.com/logs/23641245.html&amp;aid=11911&amp;sid=6235007045041189&amp;click=1&amp;url=http%3A//www.olomo.com/%3Fu%3D1519143&amp;v=0&amp;k=%u5982%u679C&amp;s=http%3A//www.programfan.com/article/2901.html&amp;rn=192126" target=_blank name=11>如果</a>p指向某个位于地址0x008a00的对象，当func1返回时，它仍然指向这个特定的对象。（除非func1有bug将堆弄乱了，完全有这种可能。）<br><br>　　现在假设你想要在func1中修改p的值。这是你的权利。调用者传入一个指针，然后函数给这个指针赋值。以往一般都是传双指针，即指针的指针，例如，CMyClass**。<br><br><br>MYCLASS* p = NULL；<br>func1（&amp;p）；<br><br>void func1（MYCLASS** pMyClass）；<br>{<br>*pMyClass = new MYCLASS；<br>&#8230;&#8230;<br>}<br><br><br>　　调用func1之后，p指向新的对象。在COM编程中，你到处都会碰到这样的用法--例如在<a class=vLink1 id=vad_5 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,5,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,5)" href="http://221.238.248.251/click/c1.php?r=http%3A//hiaurora.blogbus.com/logs/23641245.html&amp;aid=11779&amp;sid=6235007045041189&amp;click=1&amp;url=http%3A//www.ef.com.cn/englishfirst/general/default1.aspx%3Fetag%3DEFCN_General_AFVogate***&amp;v=0&amp;k=%u67E5%u8BE2&amp;s=http%3A//www.programfan.com/article/2901.html&amp;rn=682686" target=_blank name=5>查询</a>对象接口的QueryInterface函数中：<br><br><br>interface ISomeInterface { <br>HRESULT QueryInterface（IID &amp;iid, void** ppvObj）； <br>&#8230;&#8230; <br>}； <br>LPSOMEINTERFACE p=NULL； <br>pOb-&gt;QueryInterface（IID_SOMEINTERFACE, &amp;p）；&nbsp;&nbsp;<br><br>　　此处，p是SOMEINTERFACE类型的指针，所以&amp;p便是指针的指针，在QueryInterface返回的时候，如果调用<a class=vLink1 id=vad_1 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,1,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,1)" href="http://221.238.248.251/click/c1.php?r=http%3A//hiaurora.blogbus.com/logs/23641245.html&amp;aid=11703&amp;sid=6235007045041189&amp;click=1&amp;url=http%3A//www.ef.com.cn/englishfirst/general/default1.aspx%3Fetag%3DEFCN_General_AFVogate001&amp;v=0&amp;k=%u6210%u529F&amp;s=http%3A//www.programfan.com/article/2901.html&amp;rn=432566" target=_blank name=1>成功</a>，则变量p包含一个指向新的接口的指针。<br><br>　　如果你理解指针的指针，那么你肯定就理解指针引用，因为它们完全是一回事。如果你象<a class=vLink1 id=vad_2 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,2,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,2)" href="http://221.238.248.251/click/c1.php?r=http%3A//hiaurora.blogbus.com/logs/23641245.html&amp;aid=11913&amp;sid=6235007045041189&amp;click=1&amp;url=http%3A//www.ef.com.cn/englishfirst/portal/default.aspx%3Fetag%3DEFCN_KidsDLP_AFVogate001&amp;v=0&amp;k=%u4E0B%u9762&amp;s=http%3A//www.programfan.com/article/2901.html&amp;rn=507827" target=_blank name=2>下面</a>这样声明函数：<br><br><br>void func1（MYCLASS *&amp;pMyClass）；<br>{<br>pMyClass = new MYCLASS； <br>&#8230;&#8230;<br>} <br><br>　　其实，它和前面所讲得指针的指针例子是一码事，只是<a class=vLink1 id=vad_0 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,0,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,0)" href="http://221.238.248.251/click/c1.php?r=http%3A//hiaurora.blogbus.com/logs/23641245.html&amp;aid=11704&amp;sid=6235007045041189&amp;click=1&amp;url=http%3A//www.ef.com.cn/englishfirst/landing/autumn10/default.aspx%3Fetag%3DEFCN_Autumn2010_AFVogate%20&amp;v=0&amp;k=%u8BED%u6CD5&amp;s=http%3A//www.programfan.com/article/2901.html&amp;rn=458899" target=_blank name=0>语法</a>有所不同。传递的时候不用传p的地址&amp;p，而是直接传p本身：<br><br>　　MYCLASS* p = NULL；<br>　　func1（p）；<br><br>　　在调用之后，p指向一个新的对象。一般来讲，引用的原理或多或少就象一个指针，从语法上看它就是一个普通变量。所以只要你碰到*&amp;，就应该想到**。也就是说这个函数修改或可能修改调用者的指针，而调用者象普通变量一样传递这个指针，不使用地址操作符&amp;。<br><br>　　至于说什么场合要使用这种方法，我会说，极少。MFC在其集合类中用到了它--例如，CObList，它是一个Cobjects指针列表。<br><br><br><br>Class CObList : public Cobject {<br>&#8230;&#8230;<br><br>// 获取/修改指定位置的元素<br>Cobject*&amp; GetAt（POSITION position）；<br>Cobject* GetAt（POSITION position） const；<br>}；<br><br><br>　　这里有两个GetAt函数，功能都是获取给定位置的元素。区别何在呢？<br><br>　　区别在于一个让你修改列表中的对象，另一个则不行。所以如果你写成下面这样： Cobject* pObj = mylist.GetAt（pos）；<br><br>　　则pObj是列表中某个对象的指针，如果接着<a class=vLink1 id=vad_3 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,3,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,3)" href="http://221.238.248.251/click/c1.php?r=http%3A//hiaurora.blogbus.com/logs/23641245.html&amp;aid=11781&amp;sid=6235007045041189&amp;click=1&amp;url=http%3A//www.ef.com.cn/englishfirst/landing/autumn10/default.aspx%3Fetag%3DEFCN_Autumn2010_AFVogate%20&amp;v=0&amp;k=%u6539%u53D8&amp;s=http%3A//www.programfan.com/article/2901.html&amp;rn=514931" target=_blank name=3>改变</a>pObj的值： pObj = pSomeOtherObj；<br><br>　　这并改变不了在位置pos处的对象地址，而仅仅是改变了变量pObj。但是，如果你写成下面这样： Cobject*&amp; rpObj = mylist.GetAt（pos）；<br><br>　　现在，rpObj是引用一个列表中的对象的指针，所以当改变rpObj时，也会改变列表中位置pos处的对象地址--换句话说，替代了这个对象。这就是为什么CObList会有两个GetAt函数的缘故。一个可以修改指针的值，另一个则不能。注意我在此说的是指针，不是对象本身。这两个函数都可以修改对象，但只有*&amp;版本可以替代对象。 <br><br>　　在C/C++中引用是很重要的，同时也是高效的处理手段。所以要想成为C/C++高手，对引用的概念没有透彻的理解和熟练的应用是不行的。 
<img src ="http://www.cppblog.com/doing5552/aggbug/127994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/doing5552/" target="_blank">doing5552</a> 2010-09-28 22:06 <a href="http://www.cppblog.com/doing5552/archive/2010/09/28/127994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>细说HTML元素的ID和Name属性的区别</title><link>http://www.cppblog.com/doing5552/archive/2010/09/22/127323.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Wed, 22 Sep 2010 02:39:00 GMT</pubDate><guid>http://www.cppblog.com/doing5552/archive/2010/09/22/127323.html</guid><wfw:comment>http://www.cppblog.com/doing5552/comments/127323.html</wfw:comment><comments>http://www.cppblog.com/doing5552/archive/2010/09/22/127323.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/doing5552/comments/commentRss/127323.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/doing5552/services/trackbacks/127323.html</trackback:ping><description><![CDATA[&nbsp;可以说几乎每个做过Web开发的人都问过，到底元素的ID和Name有什么区别阿？为什么有了ID还要有Name呢?! 而同样我们也可以得到最classical的答案：ID就像是一个人的身份证号码，而Name就像是他的名字，ID显然是唯一的，而Name是可以重复的。<br><br>&nbsp;&nbsp;&nbsp; 上周我也遇到了ID和Name的问题，在页面里输入了一个input type="hidden"，只写了一个ID='SliceInfo'，赋值后submit，在后台用Request.Params["SliceInfo"]却怎么也去不到值<img height=19 src="http://www2.cnblogs.com/Emoticons/emdgust.gif" width=19 border=0>。后来恍然大悟因该用Name来标示，于是在input里加了个Name='SliceInfo'，就一切ok了。<br><br>&nbsp;&nbsp;&nbsp; 第一段里对于ID和Name的解答说的太笼统了，当然那个解释对于ID来说是完全对的，它就是Client端HTML元素的Identity。而Name其实要复杂的多，因为Name有很多种的用途，所以它并不能完全由ID来代替，从而将其取消掉。具体用途有：<br><br>&nbsp;&nbsp;&nbsp; 用途1: 作为可与服务器交互数据的HTML元素的服务器端的标示，比如input、select、textarea、和button等。我们可以在服务器端根据其Name通过Request.Params取得元素提交的值。<br>&nbsp;&nbsp;&nbsp; 用途2: HTML元素Input type='radio'分组，我们知道radio button控件在同一个分组类，check操作是mutex的，同一时间只能选中一个radio，这个分组就是根据相同的Name属性来实现的。<br>&nbsp;&nbsp;&nbsp; 用途3: 建立页面中的锚点，我们知道&lt;a href="URL"&gt;link&lt;/a&gt;是获得一个页面超级链接，如果不用href属性，而改用Name，如：&lt;a name="PageBottom"&gt;&lt;/a&gt;，我们就获得了一个页面锚点。<br>&nbsp;&nbsp;&nbsp; 用途4: 作为对象的Identity，如Applet、Object、Embed等元素。比如在Applet对象实例中，我们将使用其Name来引用该对象。<br>&nbsp;&nbsp;&nbsp;&nbsp;用途5: 在IMG元素和MAP元素之间关联的时候，如果要定义IMG的热点区域，需要使用其属性usemap，使usemap="#name"(被关联的MAP元素的Name)。<br>&nbsp;&nbsp;&nbsp; 用途6: 某些特定元素的属性，如attribute，meta和param。例如为Object定义参数&lt;PARAM NAME = "appletParameter" VALUE = "value"&gt;或Meta中&lt;META NAME = "Author" CONTENT = "Dave Raggett"&gt;。<br><br>&nbsp;&nbsp;&nbsp; 显然这些用途都不是能简单的使用ID来代替掉的，所以HTML元素的ID和Name的却别并不是身份证号码和姓名这样的区别，它们更本就是不同作用的东西。<br><br>&nbsp;&nbsp;&nbsp; 当然HTML元素的Name属性在页面中也可以起那么一点ID的作用，因为在DHTML对象树中，我们可以使用document.getElementsByName来获取一个包含页面中所有指定Name元素的对象数组。Name属性还有一个问题，当我们动态创建可包含Name属性的元素时，不能简单的使用赋值element.name = "..."来添加其Name，而必须在创建Element时，使用document.createElement('&lt;element name = "myName"&gt;&lt;/element&gt;')为元素添加Name属性。这是什么意思啊？看下面的例子就明白了。
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<div><img id=Codehighlighter1_30_141_Open_Image onclick="this.style.display='none'; Codehighlighter1_30_141_Open_Text.style.display='none'; Codehighlighter1_30_141_Closed_Image.style.display='inline'; Codehighlighter1_30_141_Closed_Text.style.display='inline';" src="http://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_30_141_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_30_141_Closed_Text.style.display='none'; Codehighlighter1_30_141_Open_Image.style.display='inline'; Codehighlighter1_30_141_Open_Text.style.display='inline';" src="http://www2.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">script&nbsp;</span><span style="COLOR: #ff0000">language</span><span style="COLOR: #0000ff">="JavaScript"</span><span style="COLOR: #0000ff">&gt;</span><span id=Codehighlighter1_30_141_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www2.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_30_141_Open_Text><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"><br><img src="http://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">var</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;input&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;document.createElement('INPUT');<br><img src="http://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>input.id&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;'myId';<br><img src="http://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>input.name&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;'myName';<br><img src="http://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>alert(input.outerHTML);<br><img src="http://www2.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">script</span><span style="COLOR: #0000ff">&gt;</span></div>
</div>
<p>&nbsp;&nbsp;&nbsp; 消息框里显示的结果是：&lt;INPUT id=myId&gt;。</p>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<div><img id=Codehighlighter1_30_134_Open_Image onclick="this.style.display='none'; Codehighlighter1_30_134_Open_Text.style.display='none'; Codehighlighter1_30_134_Closed_Image.style.display='inline'; Codehighlighter1_30_134_Closed_Text.style.display='inline';" src="http://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_30_134_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_30_134_Closed_Text.style.display='none'; Codehighlighter1_30_134_Open_Image.style.display='inline'; Codehighlighter1_30_134_Open_Text.style.display='inline';" src="http://www2.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">script&nbsp;</span><span style="COLOR: #ff0000">language</span><span style="COLOR: #0000ff">="JavaScript"</span><span style="COLOR: #0000ff">&gt;</span><span id=Codehighlighter1_30_134_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www2.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_30_134_Open_Text><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"><br><img src="http://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">var</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;input&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;document.createElement('</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&lt;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">INPUT&nbsp;name</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">myName</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&gt;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">');<br><img src="http://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>input.id&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;'myId';<br><img src="http://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>alert(input.outerHTML);<br><img src="http://www2.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">script</span><span style="COLOR: #0000ff">&gt;</span></div>
</div>
<p>&nbsp;&nbsp;&nbsp; 消息框里显示的结果是：&lt;INPUT id=myId name=myName&gt;。<br>&nbsp;&nbsp;&nbsp;&nbsp;初始化Name属性的这个设计不是IE的缺陷，因为MSDN里说了要这么做的，可是这样设计的原理什么呢？我暂时没有想太明白<img height=19 src="http://www2.cnblogs.com/emoticons/emembarrassed.gif" width=19 border=0>。<br><br>&nbsp;&nbsp;&nbsp; 这里再顺便说一下，要是页面中有n(n&gt;1)个HTML元素的ID都相同了怎么办？在DHTML对象中怎么引用他们呢？如果我们使用ASPX页面，这样的情况是不容易发生的，因为aspnet进程在处理aspx页面时根本就不允许有ID非唯一，这是页面会被抛出异常而不能被正常的render。要是不是动态页面，我们硬要让ID重复那IE怎么搞呢？这个时候我们还是可以继续使用document.getElementById获取对象，只不过我们只能获取ID重复的那些对象中在HTML Render时第一个出现的对象。而这时重复的ID会在引用时自动变成一个数组，ID重复的元素按Render的顺序依次存在于数组中。<br></p>
<img src ="http://www.cppblog.com/doing5552/aggbug/127323.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/doing5552/" target="_blank">doing5552</a> 2010-09-22 10:39 <a href="http://www.cppblog.com/doing5552/archive/2010/09/22/127323.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>