STL的stack类的对象有标识,有状态,有行为,符合引用语义;而stack又允许拷贝构造,同时相等性比较又重载了==进行值比较,符合值语义。那么从值和引用的角度,我们应该如何看待STL的stack呢?
如何看待STL的stack?
(5 posts) (2 voices)-
Posted 8 months ago #
-
首先,你的问题可以推广到STL的一切container类,而不必限于stack类。
其次,所有container类都是引用语义的。原因很简单,虽然container允许复制,但复制后的两个container是各自独立变化的,而且其标识是有显著意义的(引用语义!=noncopyable)。
最后,虽然STL中的container类本身是引用语义的,但其运算却是基于值语义的。为何如此设计呢?一个简单的答案是:C++中的array便是如此的( ISO C++ standard:no arrays of references),如果STL中的container的用法与最基本的数组不同,显然有违直觉的。稍微复杂的说明如下:
假设container的运算是基于引用语义的。
Container c1, c2;
Element el;
c1.insert(el);
c2.insert(el);
此时如果改变c1中el的值,将会同时改变c2中el的值,而这未必是设计者的初衷。
再假设:
Container c;
{
Element el;
c.insert(el);
}
...// 此时el出了有效范围,将被析构,那么c岂不是含有了一个illegal的元素?如果用户的确需要引用语义的container运算呢?很简单,让container的运算作用于element对象的指针即可。但这时就要特别注意element对象的生命周期问题了。
Posted 8 months ago # -
STL container重载==进行内容比较这点不是很好理解。既然是引用语义的相等性是基于标识的,那么为什么要重载==进行内容比较呢?
Posted 8 months ago # -
这个并不奇怪。首先,如果只在乎标识,直接比较两个container对象的指针(地址)即可,重载==进行内容比较是额外的福利。其次,即使对同一个类型的container,尽管是引用语义,但在某些场合也可能非常关注其内容。比如,Set是一种container,对于两个Set对象,我们可能需要比较它们内容之间的关系,如用operator==来判断两个集合是否值相同,用operater<和operator>结合不同的comparator来进行子集排序、字典排序等等。这就好比两个不同的人,本身应该是引用语义的,但有时我们会比较他们的值,比如身高、体重、速度等等,甚至在一定context下只要我们所关心的值是相等的,便认为他们是可以互换的(interchangeable),此时实际上已经是值语义了。
换言之,一个类型究竟是引用语义还是值语义,不仅与类型本身有关,也与所用的场合有关。Posted 8 months ago # -
>>一个类型究竟是引用语义还是值语义,不仅与类型本身有关,也与所用的场合有关。
我也是这样想的。事物本身没有绝对的值语义还是引用语义,在建模的时候我们可以根据需要采用不同的语义模型。在实现上,受语言的限制难免会有副作用,这是需要根据语义小心使用。
Posted 8 months ago #
Reply
You must log in to post.