C++ 将向量迭代器转换为指针

C++ 将向量迭代器转换为指针,c++,C++,有没有办法将向量::迭代器转换为指针而不访问向量本身?仅当矢量可用时,此功能才起作用: typedef vector<int> V; int* to_pointer1( V& v, V::iterator t ) { return v.data() + (t-v.begin() ); } 事实上,我本以为这是一个非常基本和流行的问题,但由于某种原因,我找不到它。不,这在目前是不可能的连续迭代器:对随机访问迭代器的改进从中提出了一个自由函数std::pointer\u

有没有办法将
向量::迭代器
转换为指针而不访问向量本身?仅当
矢量可用时,此功能才起作用:

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

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

不,这在目前是不可能的连续迭代器:对随机访问迭代器的改进
中提出了一个自由函数
std::pointer\u,可满足您的要求:

表达式:
std::pointer\u来自(a)

返回类型:
参考

操作语义:如果
a
是可解引用的,
std::address_of(*a)
;否则,如果可以从可解引用迭代器
b
访问
a
std::pointer_从(b)+(a–b)
;否则为有效指针值([basic.component])

我使用此模板:

template<typename It>
inline auto ptr(It const&it) -> decltype(std::addressof(*it))
{ return std::addressof(*it); }
模板
内联自动ptr(It const&It)->decltype(std::addressof(*It))
{return std::addressof(*it);}

实际上,这将适用于大多数迭代器。例外情况是未定义
*it
vector::iterator
)或
it
不指向任何地方(而不是指向最后一个元素的过去)的对象。出于您的特殊目的,除了向量(当指针的概念不合理时)之外,它应该是可以的。

一般来说,您不能保证存在与引用普通向量项的迭代器相对应的指针

特别是
std::vector
是专门化的,因此
和*it
甚至不会编译

然而,对于其他向量来说,只有1个正式的学究会阻止你对结束迭代器进行
&*it
。我记得,在C99中,当
p
是结束指针时,执行
&*p
在形式上是有效的,
std::vector
的目标是支持所有普通的原始数组表示法。如果我需要这样做,我只会忽略正式的迂腐,编写代码以期将来对标准进行一些修订,从而消除想象中的障碍

所以,在实践中,只需执行
&*它
:)

#包括
#包括
使用名称空间std;
auto main()->int
{
向量x(5);

cout对于end迭代器,您所要求的是不可能的;根据定义,end迭代器指向超过数组末尾的假设元素(即,取消引用它,总是UB)

你说:


@Nick我希望它对任何有效的迭代器都有效,包括end。这应该是可能的,因为to_pointer1也涵盖了这种情况


to_pointer1不包括这种情况。to_pointer1返回无效的内存地址(实际上该地址可能有效,但没有数据).

我认为它不应该适用于结束迭代器-它表示刚刚超过最后一个元素,取消引用此指针是未定义的行为。@Nick我希望它适用于任何有效的迭代器,包括结束。这应该是可能的,因为
to_pointer1
也涵盖了这种情况。
*它对于end迭代器,是吗?调试模式下的GCC不喜欢它,并在运行时退出以获得
it=vec.end()
。clang对此很满意,即使是
-Weverything
。我不认为
addressof(*(vector::end())
无效,尽管对于某些迭代器(从那里
end()
指向null)会的。@pentadecagon调试模式下的GCC是什么意思?我试过编译(没有警告)的
g++-std=c++11-g-Wall-Wextra-pedantic
运行时,即使为结束迭代器提供了预期的地址也没有出错。请尝试
-D_GLIBCXX_DEBUG
,如本文所述:谢谢。这是一个坏消息,也是一个好消息:-)我想知道为什么要花这么长时间来解决此问题。
到_pointer1
的问题到底是什么?正如您所说的,地址是有效的。@pentadegon,如果使用返回的结束迭代器地址是数组最后一个元素的“过去一个”。这可能是为应用程序中的其他内容分配的地址,也可能是为向量分配的块中的地址(如果向量分配的元素多于其大小)或者未使用内存中的地址。理论上,它也可以是分配给另一个应用程序的内存中的地址(虽然在实践中可能不会发生)。此外,如果向量为空,则可能是
vector.data()的结果+xyz;
nullptr+xyz;
。当然。但我看不出这是个什么问题。它仍然是一个有效指针,我可以用它做指针算术,它至少和结束迭代器一样有用,但更通用,因为我可以将它传递给C函数。它不是一个有效指针,它是一个指向内存的指针,可能无法访问,未使用,向量中内存块的一部分,或指向其他对象。虽然它允许您执行相同的操作,但这样做是不安全的。在调用站点,您可能记得使用指针是不安全的,但如果您将指针传递给其他函数(如您所建议的)该函数无法确定指针是否有效(除非您也传递该信息)。您正在寻找此实现的问题。@utnapistim
向量
的目的是可以将
数据()
视为大小
大小()数组的开始
,这意味着
数据()+大小()
是一个有效但不可引用的指针。23.3.6.4p2说“
[data(),data()+大小())
是一个有效范围”。
template<typename It>
inline auto ptr(It const&it) -> decltype(std::addressof(*it))
{ return std::addressof(*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.
}