访问向量的尾数元素地址的有效方法

Valid way of accessing the address of the one-past-end element of a vector

我想实现一个迭代器以在 for range 循环中使用自定义 class。迭代器访问 Base class 的 std::unique_ptr 的内部 std::vector 和 returns 指向子 class.

的原始指针

这是我想出的:

using upBase = std::unique_ptr<Base>;

class Test
{
   std::vector<upBase> list;
public:
   void Add(upBase&& i) { list.push_back(std::move(i)); }

   class iterator
   {
      upBase* ptr;
   public:
      iterator(upBase* p) : ptr(p)   {}
      bool         operator!=(const iterator& o) { return ptr != o.ptr; }
      iterator&    operator++()      { ++ptr; return *this; }
      Child&       operator*()       { return *(Child*)(*ptr).get(); }
      const Child& operator*() const { return *(Child*)(*ptr).get(); }

   };
   iterator begin() { return iterator(&list[0]); }
   iterator end()   { return iterator(&list[list.size()]); }
};

这在最新的编译器上运行良好(在 GodBolt 上使用 GCCClang 进行了测试MSVC) 但在使用 Visual Studio 2015end() 方法抛出 运行 时间异常:

 Debug assertion failed. C++ vector subscript out of range.

我在 Internet 上搜索了一种访问 std::vector 的尾数元素地址的正确方法,但除了复杂的指针运算外没有找到任何东西。

我最终为 begin()end() 方法提出了以下实现:

iterator begin() { return iterator(&list.front()); }
iterator end()   { return iterator(&list.back() + 1); }

这在 运行 时没有抱怨。这是访问 std::arraystd::vector 的尾数元素地址的正确方法吗?

如果不是,正确的方法是什么?

What would be the proper way?

您正在尝试 re-invent 方向盘。您不需要为您的 Test 实现 class iterator,因为您可以从list(即 std::vector<upBase>::begin std::vector<upBase>::end

因此只需通过 Test class:

中相应的成员函数使它们可用
class Test
{
    std::vector<upBase> list;
public:
    void Add(upBase&& i) { list.push_back(std::move(i)); }

    auto begin() /* const noexcept */ { return list.begin();  }
    auto end() /* const noexcept */ { return list.end(); }
};

(See a demo here)


另请注意,auto return 仅在 . If the compiler does not support C++14, you can provide it as trailing return type, as follows (assuming at least you have access to 之后才有可能):

auto begin() -> decltype(list.begin()) { return list.begin();  }
auto end() ->  decltype(list.end())    { return list.end(); }