c++ - 未初始化的复制错误

标签 c++ c++11 iterator allocator

我目前在试验我自己的 vector 类时遇到错误。更具体地说,它是一个模板化类,使用 std::allocator 类进行内存分配。更具体地说,错误出在我的范围构造函数中,它接受 2 个输入迭代器并使用“uninitialized_copy”函数进行复制。这是代码的 stub

#include <memory>
#include <iostream>

template <typename T, typename allocator_type = std::allocator<T>>
class vector
{
public:

// fill ctor 2
vector (size_t n, const T& val,
        const allocator_type& alloc = allocator_type())
  : my_alloc(alloc),
    begin_(my_alloc.allocate(n)),
    end_(begin_ + n),
    size_(n),
    capacity_(n)
{
  std::uninitialized_fill(begin(), end(), val);
}

// range ctor
template <typename InputIterator>
vector (InputIterator first, InputIterator last,
      const allocator_type& alloc = allocator_type())
  : my_alloc(alloc),
    size_(0),
    begin_(0),
    end_(0),
    capacity_(0)
{
  // Poor method for finding input container size, a better solution perhaps?
  InputIterator f = first;
  while (f++ != last)
  ++size_;

  begin_ = my_alloc.allocate(size());
  end_ = begin_ + size();
  capacity_ = size();

  std::uninitialized_copy(first, last, begin_);
}

  T* begin() { return begin_; }
  T* end() { return end_; }
  size_t size() { return size_; }
  size_t capacity() { return capacity_; }

private:
  allocator_type my_alloc;
  size_t size_, capacity_;
  T* begin_, *end_;
};

int main()
{
  vector<int> lst(10, 5);
  vector<int> lst2(lst.begin(), lst.end());
}

现在当我编译时,我收到一个错误,它说“在 struct std::iterator_traits 中没有名为 value_type 的类型,这很奇怪,因为我的其他类型的构造函数(例如填充和复制构造函数)很好。在此外,我还注意到编译器将“InputTterator”类型推断为“int”而不是“int*”。

在过去的几个小时里,我一直在努力调试它,但似乎找不到任何解决方案。任何帮助将不胜感激。

谢谢!

编辑:对不起!我的错误。发送 2 个整数作为模板参数的一部分并不是故意的。我已经编辑了上面的代码。它现在有一个合适的填充 ctor 和一个范围 ctor。 main 函数现在基于这些 ctors 创建 2 个 vector 。错误仍然存​​在。我又犯了一个大错!

最佳答案

i also noticed that the compiler deduced the "InputTterator" type to be of "int" instead of "int*".

当然可以,您通过了 int s 构造函数的参数:

vector<int> lst(10, 5);  // what else can it deduce than int?

你得到的错误是因为特化iterator_traits<int>内部使用uninitialized_copy确实没有 value_type成员(member)。

你应该做的是(为了避免仅仅为了获得它的大小而超过输入范围)是这样的(部分伪代码):

  InputIterator f = first;
  size_t current_size = 0;
  while (f != last) {
      if (current_size < size_) {
          new (begin+current_size) T(*f);
          ++current_size;
      } else {
          // allocate new buffer and copy any
          // existing elements over
          // (think about exception safety here)
      }
      ++f;
  }

这是您可以使用输入迭代器做的最好的事情。另一种选择是检查 InputIterator 的迭代器类别因此,当它允许算术运算时,您可以将标记分派(dispatch)到预先计算大小的实现。

编辑(响应 OP 的编辑):

所以你的问题是带有两个迭代器的构造函数模板在你不希望它调用的地方被调用。在 C++11 之前的标准库 vector 类中也存在同样的问题。该标准通过声明当推导的类型不是迭代器时构造函数不参与重载决策来解决。您可以使用 SFINAE 执行相同的操作:

template <typename InputIterator,
    typename ValueType = typename std::iterator_traits<InputIterator>::value_type>
vector (InputIterator first, InputIterator last,
      const allocator_type& alloc = allocator_type());

现在,当std::iterator_traits<InputIterator>::value_type不存在,重载决策将在模板参数替换期间丢弃重载,而将选择另一个。

关于c++ - 未初始化的复制错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24720200/

相关文章:

c++ - 实现可变最小值/最大值函数

c++ - iterator 和 const_iterator 之间的比较是否效率低下?

c++ - 运行时错误 : map/set iterators incompatible

android - 在 Android Studio 中调试动态加载的 native 库?

c++ - 在我的 C++ 程序中,fwrite 和 write 都不起作用

c++ - 'if' 带有模板参数或 SFINAE 是首选?

python - 将迭代器链接到平面迭代器

c++ - Assimp无法加载PLY模型的顶点颜色

c++ - Qt 获取 QWidget 来反射光线

c++ - 模板类型的成员枚举类作为函数参数