none
这是不是微软STL的一个buger呢?? RRS feed

  • 问题


  • #include <iostream>
    #include <list>
    #include <algorithm>
    using namespace std;

    template <class T>
    inline void PRINT_ELEMENTS(const T& coll,const char * optcstr = "")
    {
     typename T::const_iterator pos;

     std::cout << optcstr;
     for(pos = coll.begin(); pos != coll.end(); ++pos)
     {
      std::cout << *pos << ' ';
     }
     std::cout << std::endl;
    }

    class IntSequence
    {
    private:
     int value;
    public:
     IntSequence (int initialValue)
      : value(initialValue)
     {}

     int operator() ()
     {
      return value++;
     }
    };

    int main(int argc, _TCHAR* argv[])
    {
     list<int> coll;
     IntSequence seq(1);

     generate_n<back_insert_iterator<list<int> >, int, IntSequence&>//在这里我声明传入参数是一个IntSequence的引用 不是值传递
      (back_inserter(coll), 4, seq);//buger,这里的seq应该是IntSequence seq(1);  运行将改变seq(1)中的value为5
     PRINT_ELEMENTS(coll);

     generate_n (back_inserter(coll),
              4,
        IntSequence(42));
     PRINT_ELEMENTS(coll);

     generate_n (back_inserter(coll),
              4,
        seq);
     PRINT_ELEMENTS(coll);

     generate_n (back_inserter(coll),
              4,
        seq);
     PRINT_ELEMENTS(coll);
     return 0;
    }

     

    预测结果:

    1 2 3 4
    1 2 3 4 42 43 44 45 5 6 7 8
    1 2 3 4 42 43 44 45  5 6 7 8  5 6 7 8

    在vs2005下的真实运行结果:

    1 2 3 4
    1 2 3 4 42 43 44 45
    1 2 3 4 42 43 44 45 1 2 3 4
    1 2 3 4 42 43 44 45 1 2 3 4 1 2 3 4
    请按任意键继续. . .

     

     

    2010年7月7日 13:38

全部回复

  • 你好!

         STL并非微软的模板库。你的问题很明显是你的代码造成的,你可以单步跟踪一下,就知道原因了!


    周雪峰
    2010年7月10日 4:14
    版主
  • 这几天我调试了程序

    虽然在函数模板中使用的是IntSequence的引用类型, 但是在generate_n这个algorithm中定义的模板中又调用了一个函数模板_Generate_n, 关键的是在给这个函数模板_Generate_n传递参数时却不是传递的引用, 而是值拷贝, 也就是重新构造了一个IntSequence对象(也就是说, 如果把这里也改成传递引用的话, 预测结果就对了). 最重要的是, 真正调用value++的代码部分恰好是在_Generate_n中.

    综上所述, 虽然传递进去的是一个IntSequence对象, 但是由于generate_n中并未调用该对象value++函数, 而是重新构造了一个IntSequence对象, 所以原来的对象并未改变.

    附上VC2005的源代码:
    // generate_n函数模板的定义
    template<class _OutIt,
    class _Diff,
    class _Fn0> inline
    _IF_CHK_(_OutIt, void) generate_n(_OutIt _Dest, _Diff _Count, _Fn0 _Func)
    { // replace [_Dest, _Dest + _Count) with _Func()
    _Generate_n(_Dest, _Count, _Func,
      _Iter_cat(_Dest), _STD _Range_checked_iterator_tag());
    // 就是这里传递的_Func作为参数时, 进行了拷贝
    }
    // _Generate_n函数模板的定义
    template<class _OutIt, class _Diff, class _Fn0, class _OutItCat>
    inline
    void _Generate_n(_OutIt _Dest, _Diff _Count, _Fn0 _Func,
      _OutItCat, _Range_checked_iterator_tag)
    { // replace [_Dest, _Dest + _Count) with _Func()
    _DEBUG_POINTER(_Dest);
    _DEBUG_POINTER(_Func);
    for (; 0 < _Count; --_Count, ++_Dest)
      *_Dest = _Func();
    }

     

     现在的问题是:这样处理的话,用visual c++写出来的代码不就存在可移植性问题了

    同样的代码,微软STL下  和  惠普的STL下  运行结果会不一样啊

    我在惠普的STL下做过测试了,结果确实不一样

     

     

    2010年7月12日 9:01