exceptional C++ item1-3

恩恩 这本书是金牌QA和RD的必备武器,每天学几章,天天乐呵呵~~

int main() 
{
  vector<Date> e;
  copy( istream_iterator<Date>( cin ),
        istream_iterator<Date>(),
        back_inserter( e ) );
  vector<Date>::iterator first =
        find( e.begin(), e.end(), "01/01/95" );
  vector<Date>::iterator last =
        find( e.begin(), e.end(), "12/31/95" );
  *last = "12/30/95";
  copy( first,
        last,
        ostream_iterator<Date>( cout, "\n" ) );
  e.insert( --e.end(), TodaysDate() );
  copy( first,
        last,
        ostream_iterator<Date>( cout, "\n" ) );
}

至少四个迭代器错误,求bug free;

不是哥眼拙,一眼看下来真的一个都没有看出来。。。擦,哥还不信咱一个RD干不了QA的活!拷贝代码,gcc一下,擦,居然编译过了。。。

好吧,哥真的要GG?NO。。。

不就是测试么,边界,特殊用例,逻辑覆盖。。。以前一个很好的QAMM还是让我学了一些东西,从边界开始看!

find完了没有判断是否真的找到,好吧,解引用错了吧?copy使用未定义的错了吧?直接贡献了三个bug。。。

坑爹呢大哭

还有一个实在找不到,看看答案:

The reason is simple, if a little obscure: On popular implementations of the standard library,vector<Date>::iterator is often simply a Date*, and the C++ language doesn't allow you to modify temporaries of builtin type. For example, the following plain-jane code is also illegal:

Date* f();    // function that returns a Date* 
p = --f();    // error, but could be "f() - 1"
结论不是很有说服力,但是说实话,我也不是能写出--vec.end()的疯子。。。


总结的原文如下:

To summarize: When using iterators, be aware of four main issues.

  1. Valid values: Is the iterator dereferenceable? For example, writing "*e.end()" is always a programming error.

  2. Valid lifetimes: Is the iterator still valid when it's being used? Or has it been invalidated by some operation since we obtained it?

  3. Valid ranges: Is a pair of iterators a valid range? Is first really before (or equal to)last? Do both really point into the same container?

  4. Illegal builtin manipulation: For example, is the code trying to modify a temporary of builtin type, as in "--e.end()" above? (Fortunately, the compiler can often catch this kind of mistake for you, and for iterators of class type, the library author will often choose to allow this sort of thing for syntactic convenience.)


总的来说呢,用迭代器的时候记着哥传授给你的四句天一真诀就妥妥的啦:

  1. 在写下*的时候,想想这个长得像钻石的该死的东西可能会真的像钻石一样cost(core)你很多
  2. 迭代器是个不忠贞的家伙,几乎会在所有的容器(list是个例外)执行插入删除时失效(迭代器的失效的原因是自增长,重新申请了内存
  3. 当需要一个迭代器范围的时候,你最好确定一下,前面的真的比后面的小?真的么?真的么?真的么?
  4. 不要尝试修改一个对你来说不存在的临时变量



iterm2

这个木有题目可以做了,不过,嗯嗯,书上的解决方案相当的完美,直接代码吧:

struct ci_char_traits : public char_traits<char> 
              // just inherit all the other functions
              //  that we don't need to replace
{
  static bool eq( char c1, char c2 )
    { return toupper(c1) == toupper(c2); }
  static bool lt( char c1, char c2 )
    { return toupper(c1) <  toupper(c2); }
  static int compare( const char* s1,
                      const char* s2,
                      size_t n )
    { return memicmp( s1, s2, n ); }
           // if available on your platform,
           //  otherwise you can roll your own
  static const char*
  find( const char* s, int n, char a )
  {
    while( n-- > 0 && toupper(*s) != toupper(a) )
    {
        ++s;
    }
    return n >= 0 ? s : 0;
  }
};

And finally, the key that brings it all together:

typedef basic_string<char, ci_char_traits> ci_string; 

直接使用traits搞定,精彩~


后一节有一个“使用继承的方式安全么?“的问题,that's a good question!

 (1) the proper uses (and improper abuses) of inheritance;知道为啥用,也知道为啥不用继承;

 (2) the implications of the fact that there are only static members;使用静态函数(符合is-a或者work-like-a的模型),

 (3) the fact that char_traits objects are never used polymorphically.从不使用多态保证了其安全性



注:迭代器失效的原因(摘自http://blog.csdn.net/zhongjiekangping/article/details/5624922):

vector迭代器的几种失效的情况: 1.当插入(push_back)一个元素后,end操作返回的迭代器肯定失效。 2.当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时first和end操作返回的迭代器都会失效。 3.当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将全部失效。

deque迭代器的失效情况: 在C++Primer一书中是这样限定的: 1.在deque容器首部或者尾部插入元素不会使得任何迭代器失效。 2.在其首部或尾部删除元素则只会使指向被删除元素的迭代器失效。 3.在deque容器的任何其他位置的插入和删除操作将使指向该容器元素的所有迭代器失效。但是:我在vs2005测试发现第一条都不满足,不知为何?等以后深入STL以后慢慢的领会吧!

只有list的迭代器好像很少情况下会失效。也许就只是在删除的时候,指向被删除节点的迭代器会失效吧,其他的还没有发现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值