ReadingLab / Discussion-for-Cpp

C++ 中文讨论区
MIT License
89 stars 63 forks source link

some question about unique_copy #9

Closed Ocxs closed 9 years ago

Ocxs commented 9 years ago

看了@pezy 的答案,更加简洁。

unique_copy(ivec.begin(), ivec.end(), back_inserter(ls));

但是我自己也写了一个,运行结果也没问题,但是有点小问题,先贴代码。

    vector<int> ivec{ 0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 6, 7, 8, 9, 9, 5, 4, 4 };
    list<int> ls;
        auto it = ivec.begin();
    sort(ivec.begin(), ivec.end());
    auto f = unique_copy(ivec.begin(), ivec.end(), it);

    for (auto iter = it; iter != f; ++iter)
    {
        ls.push_back(*iter);
    }
    for (auto c : ls)
    {
        cout << c << " ";
    }

本来没什么问题,但是看了pezy的答案后好奇unique_copy到底是怎么工作的,就去搜了一下,找到这个. 根据这个代码,

template <class InputIterator, class OutputIterator>
  OutputIterator unique_copy (InputIterator first, InputIterator last,
                              OutputIterator result)
{
  if (first==last) return result;

  *result = *first;
  while (++first != last) {
    typename iterator_traits<InputIterator>::value_type val = *first;
    if (!(*result == val))   // or: if (!pred(*result,val)) for version (2)
      *(++result)=val;
  }
  return ++result;
}

然后我又大致看了一下vs2013中unique_copy的实现,然后问题来了。 在代码中我们可以看到result是自增的,也就是说函数调用结束之后,result已经不再是原来的迭代器了,从我的这句代码也能看出,auto f = unique_copy(ivec.begin(), ivec.end(), it);,返回的是return ++result;,但是奇怪的是接下来的代码

for (auto iter = it; iter != f; ++iter)
    {
        ls.push_back(*iter);
    }

这段代码我加断点看了一下确实执行了,后面的输出也验证了这一点,但是按道理来说,it已经变了,因为unique_copy中最后会return ++it(中间过程也是有++it的),按说这里的it应该和f是一样的,为啥还会执行for循环里面代码呢?

Ocxs commented 9 years ago

我好像又突然想明白了,vs2013中函数中调用又调用,但是对于参数it(第三个位置的参数没有引用,所以并没有改变it的值)

pezy commented 9 years ago

但是对于参数it(第三个位置的参数没有引用,所以并没有改变it的值)

恩,这是传值。

话说你这问题与 unique_copy 没啥关系啊,下次你试试精简问题,譬如你想问这个 unique_copy 的实现,你可以自己写一个类似的,然后观察问题是否会重现。

这个简化问题的过程,是非常重要的一个分析问题的习惯。下次这么尝试尝试吧~

Ocxs commented 9 years ago

@pezy 嗯嗯,谢谢! :smile: