日历

September 2020
M T W T F S S
 123456
78910111213
14151617181920
21222324252627
282930  

如何看待STL的stack?

Home Forums 《冒号课堂》讨论区 如何看待STL的stack?

  • This topic is empty.
Viewing 4 reply threads
  • Author
    Posts
    • #1143
      Todd
      Member

      STL的stack类的对象有标识,有状态,有行为,符合引用语义;而stack又允许拷贝构造,同时相等性比较又重载了==进行值比较,符合值语义。那么从值和引用的角度,我们应该如何看待STL的stack呢?

    • #1380
      hui
      Keymaster

      首先,你的问题可以推广到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对象的生命周期问题了。

    • #1381
      Todd
      Member

      STL container重载==进行内容比较这点不是很好理解。既然是引用语义的相等性是基于标识的,那么为什么要重载==进行内容比较呢?

    • #1382
      hui
      Keymaster

      这个并不奇怪。首先,如果只在乎标识,直接比较两个container对象的指针(地址)即可,重载==进行内容比较是额外的福利。其次,即使对同一个类型的container,尽管是引用语义,但在某些场合也可能非常关注其内容。比如,Set是一种container,对于两个Set对象,我们可能需要比较它们内容之间的关系,如用operator==来判断两个集合是否值相同,用operater<和operator>结合不同的comparator来进行子集排序、字典排序等等。这就好比两个不同的人,本身应该是引用语义的,但有时我们会比较他们的值,比如身高、体重、速度等等,甚至在一定context下只要我们所关心的值是相等的,便认为他们是可以互换的(interchangeable),此时实际上已经是值语义了。

      换言之,一个类型究竟是引用语义还是值语义,不仅与类型本身有关,也与所用的场合有关。

    • #1383
      Todd
      Member

      >>一个类型究竟是引用语义还是值语义,不仅与类型本身有关,也与所用的场合有关。

      我也是这样想的。事物本身没有绝对的值语义还是引用语义,在建模的时候我们可以根据需要采用不同的语义模型。在实现上,受语言的限制难免会有副作用,这是需要根据语义小心使用。

Viewing 4 reply threads
  • You must be logged in to reply to this topic.
 请您评分1星(很差)2星(不行)3星(一般)4星(不错)5星(很棒)