将 end() 迭代器转换为指针
Posted
技术标签:
【中文标题】将 end() 迭代器转换为指针【英文标题】:Convert the end() iterator to a pointer 【发布时间】:2016-07-17 12:51:38 【问题描述】:切入正题:以下安全吗?
vector<int> v;
int const* last = &*v.end();
// last is never dereferenced
我担心的是,从迭代器中获取普通旧指针的技巧会强制取消对 end() 迭代器的引用,这是无效的……即使只是为了取回指针!
背景:我正在尝试创建一个由任意类型(尤其是整数和指向对象的指针)索引的条目集合。
template<class IT>
/// requires IT implements addition (e.g. int, random-access iterator)
class IndexingFamily
public:
using IndexType = IT;
IndexingFamily(IndexType first, IndexType last);
int size() const;
IndexType operator[](int i) const;
private:
IndexType first;
IndexType last;
;
template<class IT> IndexingFamily<IT>::
IndexingFamily(IndexType first, IndexType last)
: first(first)
, last(last)
template<class IT> auto IndexingFamily<IT>::
size() const -> int
return last-first;
template<class IT> auto IndexingFamily<IT>::
operator[](int i) const -> IndexType
return first+i;
template<class IT, class ET>
struct IndexedEntry
using IndexType = IT;
using EntryType = ET;
IndexType index;
EntryType entry;
;
template<class IT, class ET>
class CollectionOfEntries
public:
using IndexType = IT;
using EntryType = ET;
/// useful methods
private:
IndexingFamilyType indexingFamily;
vector<EntryType> entries;
;
struct MyArbitraryType ;
int main()
MyArbitraryType obj0, obj1, obj2;
vector<MyArbitraryType> v = obj0,obj1,obj2;
using IndexType = MyArbitraryType const*;
IndexingFamily<IndexType> indexingFamily(&*v.begin(),&*v.end());
using EntryType = double;
using IndexedEntryType = IndexedEntry<IndexType,EntryType>;
IndexedEntry entry0 = &obj0,42.;
IndexedEntry entry1 = &obj1,43.;
vector<IndexedEntryType> entries = entry0,entry1;
CollectionOfEntries coll = indexingFamily,entries;
return 0;
【问题讨论】:
FWIW,“由任意类型索引的条目集合”听起来很像地图的定义...v.data() + v.size()
会更安全。
您知道 end()
指的是最后一个元素,对吧?
@OliverCharlesworth 是的,但在我的真实案例中,地图对处理数据的方式没有帮助
@JesperJuhl 是的,理想情况下,我想要 vector取消引用 end()
迭代器会产生未定义的行为,适用于任何标准容器。
对于向量,您可以使用与end()
迭代器对应的指针
pointer_to_end = v.empty() ? 0 : (&(*v.begin()) + v.size());
或
pointer_to_end = v.data() + v.size(); // v.data() gives null is size is zero
需要检查v.empty()
,因为如果v
为空,则v.begin() == v.end()
。对于 C++11 或更高版本,使用nullptr
而不是上面的0
通常被认为是更可取的。
【讨论】:
"如果v
为空,v.begin() == v.end()
" - 为什么你会想要 0
作为这里的结果?
我明白这一点,但仍然不清楚你为什么想要它而不是 v.begin()
作为结果。
(&(*v.begin()) + v.size())
(相当于&*v.begin()
)?
如果 v.begin() == v.end()
然后取消引用 v.begin()
具有未定义的行为。
你的答案是好的,除了那个空的情况:指针越过最后一个元素的末尾,选择以统一的方式处理空范围,所以它有点失败......【参考方案2】:
成员函数end()
返回的迭代器“指向”向量的最后一个元素。您可能不会取消引用它。否则程序将有未定义的行为。
可以通过以下方式获取对应的指针
vector<int> v;
int const *last = v.data() + v.size();
如果你想使用成员函数end()返回的迭代器你可以写
vector<int> v;
int const *last = v.data() + std::distance( v.begin(), v.end() );
考虑到成员函数 data() 返回向量数据占用的内存范围的原始指针。
【讨论】:
以上是关于将 end() 迭代器转换为指针的主要内容,如果未能解决你的问题,请参考以下文章