实现vector的push_back()函数会导致意外输出?

时间:2019-05-24 00:50:22

标签: c++

我正在尝试a very noob way to implement vector作为练习。我编写了许多函数,并且看起来工作正常,但是当我尝试推入一系列值时,会导致输出结果超出预期。

我的类型定义是:

template <typename T, class Allocator = allocator<T>> class vector {
public:
  // type definitions
  using allocator_type = Allocator;
  using value_type = T;

  using reference = value_type &;
  using const_reference = const value_type &;

  using pointer = typename std::allocator_traits<Allocator>::pointer;
  using const_pointer =
      typename std::allocator_traits<Allocator>::const_pointer;

  using iterator = value_type *;
  using const_iterator = const value_type *;

  using reverse_iterator = std::reverse_iterator<iterator>;
  using const_reverse_iterator = const std::reverse_iterator<const_iterator>;

  using size_type = std::size_t;
  using difference_type = std::ptrdiff_t;

  // member variables
  allocator_type m_allocator;
  T *m_data = nullptr;

  size_type m_capacity = 10;
  size_type m_size = 0;
  ...

push_back()函数是:

template <typename T, class Allocator>
constexpr void vector<T, Allocator>::push_back(const T &val_) {
  m_data[m_size++] = val_;

  if (m_size > capacity()) {
    m_capacity = m_size * 2;
    m_data = m_allocator.allocate(m_capacity);
  }
}

当我尝试:

#include "vector.h"
#include <iostream>

int main() {
  p1v0t::vector<int> iv;

  for (int i = 0; i < 15; ++i) {
    iv.push_back(i);
  }

  for (auto item : iv) {
    std::cout << item << ' ';
  }
}

它给出如下输出: 0 0 0 0 0 0 0 0 0 0 10 11 12 13 14

可能的原因是什么?任何因我愚蠢而大喊大叫的行为都可以接受...

2 个答案:

答案 0 :(得分:4)

您在添加元素后测试容量:

m_data[m_size++] = val_;

if (m_size > capacity()) {

因此,如果m_size ==容量,则插入到末尾,然后才调整数据区域的大小。

由于初始容量为10,因此在插入第11个元素时,示例中首先遇到问题。然后m_size == 10,capacity == 10。

→您在val_上插入m_data[10]

此外,您可能想检查如何使用分配器。使用通常的分配器,您需要在增加容量(并释放旧区域)之后将项目复制到新分配的区域。从您的帖子中我们无法确定,Allocator可能是您的定制商品,行为不规范。

答案 1 :(得分:3)

m_data = m_allocator.allocate(m_capacity);

这会分配新的内存,替换旧的指针,但是旧的指针及其数据将被丢弃(泄漏)。您需要同时具有新指针和旧指针,从旧指针复制到新指针,删除旧指针并将其替换为新指针。

如其他答案所述,您的容量增加是在错误的时间发生的;只需将支票移到新元素的分配之前,并对其进行调整以测试>=而不是>即可解决此问题。