带有原始指针的stl :: iterators

时间:2017-01-31 16:46:01

标签: c++ pointers stl

我想在C ++数组中使用迭代器,但也使用原始指针。 我可以使用静态向量:

#define SIZE 10
int vect[SIZE] = {0};
vect[3] = 5;
int* p = std::find(std::begin(vect), std::end(vect), 5);
bool success = p != std::end(vect);

如何使用原始指针(可能是堆分配的向量)来实现? 当然编译器不知道数据的大小,所以这段代码

int* pStart = vect;
std::find(std::begin(pStart), std::end(pStart), 5);

给出

error C2784: '_Ty *std::begin(_Ty (&)[_Size])' : 
could not deduce template argument for '_Ty (&)[_Size]' from 'int *'

是否可以让begin()end()了解它?

5 个答案:

答案 0 :(得分:4)

  

是否可以让begin()和end()知道它?

可以为指针实现std::begin,但是不可能实现std::end(因为正如你所说,大小未知),所以它有点无意义

但是,您不需要其中任何一个使用std::find

int* p = std::find(pStart, pStart + SIZE, 5);

答案 1 :(得分:4)

不能在指针上使用std::beginstd::end。与大小是类型的一部分的数组不同,因此指针不能保持它指向的东西的大小。在您使用指针的情况下,您必须使用

std::find(pStart, pStart + SIZE, 5);

避免这种情况的方法是在你不知道编译时szie是什么时使用std::vector。它将为您管理内存并提供beginend成员函数。

答案 2 :(得分:2)

下面:

std::begin(pStart), std::end(pStart)

你试图抓住指针的开头和结尾。都能跟得上!

相反,你的意思是:

std::begin(vect), std::end(vect)

无论您使用数组,std::arraystd::vector还是特别大的大象 - 来获取容器的边界,都需要容器。

答案 3 :(得分:0)

  

我想在C ++数组中使用迭代器,但也使用原始指针。

你倒退了。原始指针迭代器。他们遍历数组。

您可以将它们用于std::beginstd::end所能完成的所有事情。最值得注意的是,您可以将它们传递给<algorithm>中的C ++标准算法。

指针本身不能被迭代。迭代器不能被迭代。

int* pStart = vect;
std::find(std::begin(pStart), std::end(pStart), 5);

非常宽松地说,指针只是一个数字。数字的“开始”和“结束”是什么?这段代码没有下列意义:

int i = 123;
std::find(std::begin(i), std::end(i), 5); // error
  

是否可以让begin()end()了解它?

指针可能指向某个数组的开头。但是这些知识必须与指针一起保存。您需要维护一个大小或结束指针以及一个开始指针,并将所有数据保存在一起。

这正是std::arraystd::vector为你做的事情。

答案 4 :(得分:0)

当我处理数组时,我依靠简单的容器使它们与C ++对范围的一般处理兼容。

例如:

#include <iostream>
#include <memory>    // for std::unique_ptr
#include <algorithm> // for std::reverse
#include <numeric>   // for std::iota

template<typename T>

class range_view {

 public:

  range_view(T* data, std::size_t size)
      : m_data { data },
        m_size { size } { }

  const T* begin() const { return m_data; }
  const T* end() const { return m_data + m_size; }

  T* begin() { return m_data; }
  T* end() { return m_data + m_size; }

 private:

  T* m_data;
  std::size_t m_size;
};

int main() {

  // this is your actual data
  auto pdata = std::make_unique<int>(20);

  // this is a handle you use to work with your data
  auto data_view = range_view<int>(pdata.get(), 20);

  // for example, you can fill it with numbers 0, ... , N - 1
  std::iota(data_view.begin(), data_view.end(), 0);

  // it is now compatible with c++'s range-based operators
  std::cout << "my data...\n";
  for(auto && item : data_view) std::cout << item << " ";

  std::reverse(data_view.begin(), data_view.end());
  std::cout << "\nreversed...\n";
  for(auto && item : data_view) std::cout << item << " ";
  std::cout << "\n";
}

编译并运行

$ g++ example.cpp -std=c++14
$ ./a.out
my data...
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
reversed...
19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 

您仍然需要担心将正确的维度传递给构造函数,如果基础指针被删除,它将会失败,但无论如何您都不得不担心。