MyTinySTL icon indicating copy to clipboard operation
MyTinySTL copied to clipboard

basic_string.h:逻辑问题

Open InitialZJ opened this issue 1 year ago • 4 comments

  • 在insert函数中
// 在 pos 处插入 n 个元素
template <class CharType, class CharTraits>
typename basic_string<CharType, CharTraits>::iterator
basic_string<CharType, CharTraits>::
insert(const_iterator pos, size_type count, value_type ch)
{
  iterator r = const_cast<iterator>(pos);
  if (count == 0)
    return r;
  if (cap_ - size_ < count)
  {
    return reallocate_and_fill(r, count, ch);
  }
  if (pos == end())
  {
    char_traits::fill(end(), ch, count);
    size_ += count;
    return r;
  }
  char_traits::move(r + count, r, count);
  char_traits::fill(r, ch, count);
  size_ += count;
  return r;
}

char_traits::move(r + count, r, count)应改为char_traits::move(r + count, r, end() - pos)

  • 同理
// 在 pos 处插入 [first, last) 内的元素
template <class CharType, class CharTraits>
template <class Iter>
typename basic_string<CharType, CharTraits>::iterator
basic_string<CharType, CharTraits>::
insert(const_iterator pos, Iter first, Iter last)
{
  iterator r = const_cast<iterator>(pos);
  const size_type len = mystl::distance(first, last);
  if (len == 0)
    return r;
  if (cap_ - size_ < len)
  {
    return reallocate_and_copy(r, first, last);
  }
  if (pos == end())
  {
    mystl::uninitialized_copy(first, last, end());
    size_ += len;
    return r;
  }
  char_traits::move(r + len, r, len);
  mystl::uninitialized_copy(first, last, r);
  size_ += len;
  return r;
}

char_traits::move(r + len, r, len)应改为char_traits::move(r + len, r, end() - pos)

InitialZJ avatar Nov 12 '23 06:11 InitialZJ

对于字符串move函数定义如下

  // 字符串移动(复制),允许复制的两个地址段有重复,具体操作是更具源地址和目的地址关系选择从前后复制还是从后向前复制
  static char_type* move(char_type* dst, const char_type* src, size_t n)
  {
    char_type* r = dst;
    if (dst < src)
    {
      for (; n != 0; --n, ++dst, ++src)
        *dst = *src;
    }
    else if (src < dst)
    {
      dst += n;
      src += n;
      for (; n != 0; --n)
        *--dst = *--src;
    }
    return r;
  }

最后一个参数n的类型是size_t类型,这里使用count作为移动字符的数目应该没有问题

myc13381 avatar Jan 11 '24 02:01 myc13381

对于字符串move函数定义如下

  // 字符串移动(复制),允许复制的两个地址段有重复,具体操作是更具源地址和目的地址关系选择从前后复制还是从后向前复制
  static char_type* move(char_type* dst, const char_type* src, size_t n)
  {
    char_type* r = dst;
    if (dst < src)
    {
      for (; n != 0; --n, ++dst, ++src)
        *dst = *src;
    }
    else if (src < dst)
    {
      dst += n;
      src += n;
      for (; n != 0; --n)
        *--dst = *--src;
    }
    return r;
  }

最后一个参数n的类型是size_t类型,这里使用count作为移动字符的数目应该没有问题

移动字符的数目就有问题,应该是先把pos到end()这一段往后移动count,再把[first, last)拷贝进来,所以移动数目是end()-pos,对应dst是r+count,src是r。

InitialZJ avatar Jan 11 '24 02:01 InitialZJ

我看了一下,确实如此,如果move第三个参数传递count,可能会导致某些值被覆盖而不是被移动,这逻辑确实有问题,还是等作者回复吧

myc13381 avatar Jan 11 '24 03:01 myc13381

是不是应该先将first到last之间的元素拷贝下来,在移动,因为移动可能改变了first和last指向的元素位置或者basic_string重新分配了内存

jsuwcp avatar Jan 22 '24 14:01 jsuwcp