将迭代器转换为指针?

时间:2009-04-13 04:41:45

标签: c++ stl pointers vector iterator

我有std::vectorn元素。现在我需要将一个指针传递给一个函数的最后n-1个元素的向量。

例如,我的vector<int> foo包含(5,2,6,87,251)。函数需要vector<int>*,我想传递一个指向(2,6,87,251)的指针。

我可以(安全地)使用迭代器++foo.begin(),将其转换为指针并将其传递给函数吗?或者使用&foo[1]

UPDATE:人们建议我更改我的函数以获取迭代器而不是指针。这似乎在我的情况下是不可能的,因为我提到的函数是find的{​​{1}}函数。那么在这种情况下,是将unordered_set<std::vector*>元素从n-1复制到一个新向量中,并使用指向唯一选项的指针调用foo?非常低效!这就像画家Shlemiel,特别是因为我必须查询许多子集:最后find,然后是n-1等元素,看看它们是否在n-2

13 个答案:

答案 0 :(得分:80)

这里是,获取对迭代器使用的相应指针的引用:

示例:

string my_str= "hello world";

string::iterator it(my_str.begin());

char* pointer_inside_buffer=&(*it); //<--

[通知运营商*返回参考这样做&amp;在引用上会给你地址]。

答案 1 :(得分:8)

  

在我的情况下似乎不可能,因为我提到的功能是unordered_set<std::vector*>的查找功能。

您使用的是自定义哈希/谓词函数对象吗?如果没有,那么您必须将unordered_set<std::vector<int>*>::find()指针传递给您想要找到的确切向量。指向具有相同内容的另一个向量的指针将不起作用。至少可以说,这对于查找不是很有用。

使用unordered_set<std::vector<int> >会更好,因为您可以按值执行查找。我认为这还需要一个自定义哈希函数对象,因为hash据我所知不具备vector<int>的特化。

无论哪种方式,指向矢量中间的指针本身不是矢量,正如其他人所解释的那样。您无法将迭代器转换为指向vector的指针而不复制其内容。

答案 2 :(得分:6)

如果可以,更好的选择可能是更改函数以将元素的迭代器或全新的向量(如果它不修改)。

虽然您可以使用数组执行此类操作,因为您知道它们是如何存储的,但使用向量执行相同操作可能是个坏主意。 &foo[1]没有vector<int>*类型。

此外,虽然在线提供STL实现,但尝试依赖抽象的内部结构通常存在风险。

答案 3 :(得分:3)

你的功能不应该vector<int>*;应视情况采用vector<int>::iteratorvector<int>::const_iterator。然后,只需传入foo.begin() + 1

答案 4 :(得分:3)

vector是一个拥有其元素完全所有权的容器。一个向量不能保持另一个向量的局部视图,甚至是const视图。这是根本原因。

如果您需要,请创建自己的容器,其中包含对数据的weak_ptr视图,或查看范围。一对迭代器(甚至指针在迭代器中很好地作为迭代器),或者更好的是,boost :: iterator_range可以非常无缝地工作。

这取决于代码的模板性。如果需要隐藏cpp中的代码,请使用std :: pair。

答案 5 :(得分:2)

你问题的直接答案是肯定的。如果foo是一个向量,你可以这样做:&amp; foo [1]。

这仅适用于矢量,因为标准表示矢量通过使用可靠的存储器来实现存储。

但你仍然可以(并且可能应该)传递迭代器而不是原始指针,因为它更具表现力。传递迭代器不会复制矢量。

答案 6 :(得分:1)

  

例如,我的vector<int> foo包含(5,2,6,87,251)。函数需要vector<int>*,我想传递一个指向(2,6,87,251)的指针。

指向vector<int>的指针与指向向量元素的指针完全不同。

为了做到这一点,你需要创建一个新的vector<int>,只需要你想要的元素来传递指针。类似的东西:

 vector<int> tempVector( foo.begin()+1, foo.end());

 // now you can pass &tempVector to your function

但是,如果你的函数使用指向int的数组的指针,那么你可以传递&foo[1]

答案 7 :(得分:1)

使用vector::front,它应该是最便携的解决方案。当我与一个需要char ptr的固定API接口时,我已经使用过这个。例如:

void funcThatTakesCharPtr(char* start, size_t size);

...

void myFunc(vector<char>& myVec)
{
    // Get a pointer to the front element of my vector:
    char* myDataPtr = &(myVec.front());

    // Pass that pointer to my external API:
    funcThatTakesCharPtr(myDataPtr, myVec.size());
}

答案 8 :(得分:0)

如果你的函数真的需要vector<int> *(指向向量的指针),那么你应该传递&foo,因为那将是一个指向向量的指针。显然,这不会简单地解决你的问题,但你不能直接将迭代器转换为向量,因为迭代器地址处的内存不会直接寻址有效的向量。

您可以通过调用vector constructor

来构建新的向量
template <class InputIterator> vector(InputIterator, InputIterator)

这通过复制两个迭代器之间的元素来构造一个新的向量。你会大致使用它:

bar(std::vector<int>(foo.begin()+1, foo.end());

答案 9 :(得分:0)

我没有测试过这个,但你可以使用一组迭代器吗?每个迭代器对都代表序列向量的开始和结束迭代器。 E.g:

typedef std::vector<int> Seq;
typedef std::pair<Seq::const_iterator, Seq::const_iterator> SeqRange;

bool operator< (const SeqRange& lhs, const SeqRange& rhs)
{
    Seq::const_iterator lhsNext = lhs.first;
    Seq::const_iterator rhsNext = rhs.first;

    while (lhsNext != lhs.second && rhsNext != rhs.second)
        if (*lhsNext < *rhsNext)
            return true;
        else if (*lhsNext > *rhsNext)
            return false;

    return false;
}

typedef std::set<SeqRange, std::less<SeqRange> > SeqSet;

Seq sequences;

void test (const SeqSet& seqSet, const SeqRange& seq)
{
    bool find = seqSet.find (seq) != seqSet.end ();
    bool find2 = seqSet.find (SeqRange (seq.first + 1, seq.second)) != seqSet.end ();
}

显然,这些载体必须像以前一样保存在其他地方。此外,如果修改了序列向量,则必须删除该集合中的条目并重新添加,因为迭代器可能已更改。

乔恩

答案 10 :(得分:0)

Vector是一个模板类,将类的内容转换为指针是不安全的: 您无法继承vector类以添加此新功能。 并且更改函数参数实际上是一个更好的主意。 Jst创建另一个int向量 vector temp_foo(foo.begin [X],foo.end()); 并将此向量传递给函数

答案 11 :(得分:0)

将迭代器转换为指针的安全版本(正是这意味着无论其含义如何)并且安全我的意思是不必担心必须取消引用迭代器并导致由#include <iostream> #include <vector> #include <string.h> int main() { std::vector<int> vec; char itPtr[25]; long long itPtrDec; std::vector<int>::iterator it = vec.begin(); memset(&itPtr, 0, 25); sprintf(itPtr, "%llu", it); itPtrDec = atoll(itPtr); printf("it = 0x%X\n", itPtrDec); vec.push_back(123); it = vec.begin(); memset(&itPtr, 0, 25); sprintf(itPtr, "%llu", it); itPtrDec = atoll(itPtr); printf("it = 0x%X\n", itPtrDec); } /引起的可能的异常/错误其他情况

#pragma

将打印类似

的内容
  

it = 0x0

     

it = 0x2202E10

这是一种令人难以置信的hacky方式,但如果你需要它,它就能完成这项工作。您将收到一些编译器警告,如果真的困扰您,可以使用 <ul class="nav nav-tabs"> <li class="active"><a href="#One" data-toggle="tab">First</a></li> <li class=""><a href="#Two" data-toggle="tab">Second</a></li> </ul> <div id="tabContent" class="tab-content"> <div class="tab-pane fade" id="One"> //Its works fine,and assigns the value to input field. <input type="text" value="{{($row->value== 1) ?'test':'')}}" /> </div> <div class="tab-pane fade" id="Two"> //value is not assigned to input field though condition is true. <input type="text" value="{{($row->value== 1) ?'test':'')}}" /> </div> </div>

删除

答案 12 :(得分:0)

std::vector<int> v;
  :
auto it=v.end();
auto ptr=v.data()+std::distance(v.begin(),it);