将 end() 迭代器转换为指针

Bér*_*ger 5 c++ pointers iterator

开门见山:以下安全吗?

vector<int> v;
int const* last = &*v.end(); 
// last is never dereferenced
Run Code Online (Sandbox Code Playgroud)

我担心的是,从迭代器获取普通旧指针的技巧会强制取消引用 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;
}
Run Code Online (Sandbox Code Playgroud)

Pet*_*ter 3

对于任何标准容器,取消引用end()迭代器都会产生未定义的行为。

end()对于向量,您可以使用以下方法获取与迭代器相对应的指针

pointer_to_end = v.empty() ? 0 : (&(*v.begin()) + v.size());
Run Code Online (Sandbox Code Playgroud)

或者

pointer_to_end = v.data() + v.size();   // v.data() gives null is size is zero
Run Code Online (Sandbox Code Playgroud)

v.empty()需要检查,因为如果v为空,v.begin() == v.end()。对于 C++11 或更高版本,通常认为使用nullptr代替0上面的内容更可取。

  • 如果 `v.begin() == v.end()` 则取消引用 `v.begin()` 具有未定义的行为。 (3认同)
  • "*if `v` 为空,`v.begin() == v.end()`*" - 为什么你会想要 `0` 作为这里的结果? (2认同)