我有一个类封装了一个指向类MyClass
的指针的向量(指针代替实例,因为MyClass
实际上是一个广泛的子类层次结构的基类,其实例保存在集合中)。向量不能保存const指针,因为该集合拥有对象并在其析构函数中删除它们。
此集合的用户应具有对集合中项目的只读访问权限。常规const_iterator
不会在这里完成工作,因为它会允许班级用户修改项目,所以我做了这个typedef:
class MyCollection
{
private:
std::vector<MyClass*> backingCollection;
public:
typedef std::vector<MyClass const*>::const_iterator const_iterator;
MyCollection
需要有一个begin和end方法来返回这些迭代器。但是,backingCollection.begin()
会返回常规const_iterator
,因此我不得不将一个看起来非常糟糕的演员组合在一起:
inline const_iterator begin() const
{
return *reinterpret_cast<const_iterator*>(&this->backingCollection.begin());
}
当我仅在Visual Studio中编译项目时,这很好用,但是GCC讨厌它:
error: taking address of temporary [-fpermissive]
我不想仅仅因为这个而启用许可模式。
这里最好的解决方案是什么? const迭代器的整个想法是错误的吗?有没有更好的方法来转换迭代器?
答案 0 :(得分:3)
使用.data()
而不是begin,它返回指向const指针的指针,并隐式转换为指向const
指向const
的指针。对于end
返回数据加上大小。
你丢失了调试工具,这就是它。
typedef MyClass const*const* const_iterator;
inline const_iterator begin() const {
return backingCollection.data();
}
inline const_iterator end() const {
return begin()+backingCollection.size();
}
答案 1 :(得分:0)
请注意,您获取临时的地址。我认为破解转换是一个坏主意(除非可能在非常短暂的实验代码中),但是如果你要坚持它,你所要做的就是不要使对象成为临时对象:put {{1}在一个局部变量中。
答案 2 :(得分:0)
一如既往,编译器是对的 :-)
您必须在 backing_collection 的地址上使用 reinterpret_cast,然后从重新解释的地址中返回 const_iterator。
using ConstCollection = const std::vector<const MyClass*>;
inline auto begin() const {
return reinterpret_cast<ConstCollection*>&backingCollection)->cbegin();
}
inline auto end() const {
return reinterpret_cast<ConstCollection*>&backingCollection)->cend();
}