将向量迭代器转换为指针

时间:2014-06-18 08:35:23

标签: c++

有没有办法将vector::iterator转换为指针而无法访问向量本身?仅当vector可用时才有效:

typedef vector<int> V;
int* to_pointer1( V& v, V::iterator t )
{
    return v.data() + (t-v.begin() );
}

但如果没有vector左右怎么办呢?这不起作用:

int* to_pointer2( V::iterator t )
{
    // the obvious approach doesn't work for the end iterator
    return &*t;
}

事实上,我本以为这是一个非常基本和受欢迎的问题,但由于某些原因我找不到它。

4 个答案:

答案 0 :(得分:9)

一般情况下,不保证指向与引用普通向量项的迭代器对应的指针。

特别是std::vector<bool>是专门的,因此&*it甚至不会编译。

然而,对于其他向量,它只是 1 正式迂腐,阻止你对最终迭代器做&*it。在C99中,我记得,当&*p是结束指针时,p正式有效,std::vector的目标是支持所有普通的原始数组符号。如果我需要这个,我会忽略正式迂腐,并编写代码,以期对标准的未来修订将消除那个想象的障碍。

因此,在实践中,只需&*it。 :)

#include <iostream>
#include <vector>
using namespace std;

auto main() -> int
{
    vector<int> x( 5 );
    cout << &*x.begin() << " " << &*x.end() << endl;
    cout << &*x.end() - &*x.begin() << endl;        // Works nicely IN PRACTICE.
}

但要记住,你不能为vector<bool>执行此操作。


1)在评论elsewhere用户pentadecagon备注:“试试-D_GLIBCXX_DEBUG,如此处所述:gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode_using.html。” g ++经常提供一些方法将任何正式的UB带到前面,例如正式UB循环的“优化”。在这种特殊情况下的一个解决方案就是不要求它这样做,但更一般地说,人们可能必须明确要求它不这样做。

答案 1 :(得分:6)

不,目前无法实现。 n3884 连续迭代器:随机访问迭代器的改进提出了一个满足您要求的自由函数std::pointer_from

  

表达: std::pointer_from(a)
  返回类型: reference
  操作语义:如果a可解除引用,std::address_of(*a);否则,如果可以从可解除引用的迭代器ab访问std::pointer_from(b) + (a – b);否则是有效的指针值([basic.compound])。

答案 2 :(得分:1)

对于最终迭代器,您所要求的是不可能的;根据定义,结束迭代器指向一个假设的元素过去数组的末尾(即取消引用它,总是UB)。

你说:

  

@Nick我想让它适用于任何有效的迭代器,包括结尾。它应该是可能的,因为to_pointer1也涵盖了这种情况。

to_pointer1 没有涵盖此案例。 to_pointer1返回一个无效的内存地址(实际上地址可能有效,但那里没有数据)。

答案 3 :(得分:0)

我使用这个模板:

template<typename It>
inline auto ptr(It const&it) -> decltype(std::addressof(*it))
{ return std::addressof(*it); }

实际上,这适用于大多数迭代器。例外是未定义*itvector<bool>::iterator)或it 指向无处(而不是过去的最后一个元素)的对象。为了你的特殊目的,它应该没问题,除了vector<bool>(当指针的概念不合理时)。