• [转载] C++ STL中判断list为空,size()==0和empty()有什么区别


    关于两个的区别,首先size()==0为bool表达式,empty()为函数调用,这一点很明显。查看源代码,

        bool empty() const { return _M_node->_M_next == _M_node; }  
    
        size_type size() const {  
          size_type __result = 0;  
          distance(begin(), end(), __result);  
          return __result;  
        }  

    可以看出empty直接检查标记节点,而size是通过求首尾迭代器的距离来获取元素个数的。

    查看的源代码来自http://www.sgi.com/tech/stl/download.html

     Effective STL中文版:50条有效使用STL的经验

    对任一容器c ,下面的代码
    if (c.size() == 0)…

    本质上与
    if (c.empty())…

    是等价的。既然如此,你或许会疑惑为什么要偏向于某一种形式,尤其是考虑到empty 通常被
    实现为内联函数(inline function ),并且它所做的仅仅是返回 size 是否为0。

    你应该使用empty 形式,理由很简单:empty 对所有的标准容器都是常数时间操作,而对一些list 实现,size 耗费线性时间。

    到底是什么使list 这么讨厌呢?为什么它不也提供常数时间的size 呢?答案在于list 所独有的链接(splice)操作。考虑如下代码:
    list<int> list1;
    list<int> list2;

    list1.splice( //把list2中从第一个含5 的节点
        list1.end(), list2,  //到最后一个含10的所有节点
        find(list2.begin(), list2.end(), 5), //移动到list1的末尾
        find(list2.rbegin(), list2.rend(), 10).base()
     //关于base() 调用的信息,见第28条
    );

    这段代码只有当list2 中在含5 的节点之后有含10的节点时才工作。假定这不是一个问题,而把注意力集中在下面这个问题上:链接后的list1 中有多少个元素?很明显,链接后的list1 中的元素个数是它链接前的元素个数加上链接过来的元素个数。但有多少个元素被链接过来了
    呢?应该与find(list2.begin(), list2.end(), 5)和find(list2.rbegin(), list2.rend(), 10). base() 所定义的区间中的元素个数一样多。好,那究竟是多少个呢?如果不遍历该区间来数一数,你是没法知道的。问题就在这里。

    假定由你来负责实现list。list 不仅是容器,而且是标准容器,它将会被广泛使用。你自然会希望自己的实现尽量高效。你发现用户通常希望知道 list 中有多少个元素,所以你想使 size 成为常数时间操作。因此,你希望设计list,使它总知道自己含有多少个元素。

    同时,你知道在所有的标准容器中,只有list 具有把元素从一处链接到另一处而不需要拷贝任何数据的能力。你推断,许多 list 的客户之所以选择它,是因为它提供了高效的链接操作。他们知道把一个区间从一个list 链接到另一个list 可以通过常数时间来完成。你很清楚他们知道这一点,所以你当然想满足他们的期望,使splice成为常数时间的成员函数。

    这将使你左右为难。如果 size 是常数时间操作,那么 list 的每个成员函数都必须更新它们所操作的链表的大小(size ),当然也包括 splice。可是 splice更新它所改变的链表的大小的唯一方式是计算所链接的元素的个数,而这会使 splice不具有你所希望的常数时间操作性能。如果你不要求splice更新它所改变的链表的大小,则splice可以成为常数时间操作,可是这时size 会成为线性时间操作。通常,它需要遍历自己的整个数据结构来看一看自己含有多少个元素。不管你怎么看,某些方面——list 或splice——必须做出让步。其中的一个可以成为常数时间操作,但不可能二者都是。

    不同的链表实现通过不同的方式解决这一冲突,具体方式取决于作者选择把 size 还是splice实现得最为高效。如果你使用的list 实现恰好是把splice的常数时间操作放在第一位的,那么你使用empty 而不是size 会更好些,因为empty 操作总是花费常数时间。即使现在你使用的list 实现不是这种方式,将来你也可能会发现自己在使用这样的实现。比如,你可能把自己的代码移植到不同的平台上,该平台上的 STL 采用了不同的实现;又如,你可能决定切换到当前平台上的不同的STL 实现。

    不管发生了什么,调用empty 而不是检查size==0 是否成立总是没错的。所以,如果你想知道容器中是否含有零个元素,请调用empty。

     
     
     
  • 相关阅读:
    Cheatsheet: 2018 11.01 ~ 2019 02.28
    Cheatsheet: 2018 08.01 ~ 2018 10.31
    Cheatsheet: 2018 05.01 ~ 07.31
    Cheatsheet: 2018 04.01 ~ 04.30
    stb_image multiple definition of first defined here 多文件包含问题
    NanoPi arm架构下的程序 ./ 运行黑屏 Qt环境可运行
    opencv3.4.9 + armv7 + arm-linux-gnueabihf交叉编译
    NIVIDIA Tegra K1 QWT安装使用问题和解决办法
    7.17日报
    7.16日报
  • 原文地址:https://www.cnblogs.com/pjl1119/p/8892318.html
Copyright © 2020-2023  润新知