【发布时间】:2017-09-02 07:11:33
【问题描述】:
这是:
auto& ref1 = *it++;
ref1 = expression; // (1)
前向迭代器所需的语义之一?那么随机访问迭代器呢?
auto& ref1 = it[3];
ref1 = expression; // (2)
根据cppreference,需要前向迭代器:
// Return reference, which equals to (const) value_type &
*it++ === value_type&
对于随机访问迭代器:
it[n] === *(it + n)
这是相同的情况,这意味着在这两种情况下,您都在取消引用临时(迭代器)。在我的例子中,我的迭代器通过复制一个索引来存储,该索引允许访问一个不提供对存储元素的直接访问的容器,只能通过索引。
效果很好:
*it++ = value;
因为it 的临时副本具有句子范围。
但在这种情况下:
type& val = *it++;
val = 3;
我们得到了未定义的行为,因为副本已经在第二行被销毁了。
在我的情况下,我有一个 QModelIndex 包装器来获取/保存到 QAbstractItemModel 的数据/保存。该模型只为您提供存储在模型上的QVariants 的副本。
我的包装器类(operator= 重载的value_type)保存了QModelIndex 的一个实例(用于操作模型),而迭代器则保存了该包装器的一个实例。所以,如果迭代器被销毁,包装器和索引也会被销毁。
只要不需要支持(1) 和(2) 行,我想我可以解决这两个问题。
注意:我的实现或多或少是这样的(简化的):
// The value type
struct index
{
QModelIndex qidx;
index& operator=(QVariant const& val)
{
if (qidx.isValid())
qidx.model()->setData(qidx, val);
return *this;
}
};
// Private class actually. The "movements" cannot be done
// over the value type because it will cause, in functions
// returning references to the value type, to increase the chaos.
// So, I make the index points to different model items using
// this class.
struct index_manipulator
{
QModelIndex& qidx;
void move(int rows, int cols)
{
if (qidx.isValid())
qidx = qidx.model()->index(qidx.row() + rows,
qidx.column() + cols);
}
};
struct index_safe_ref
{
mutable index idx;
operator index&() const { return idx; }
};
struct my_row_it
{
index idx;
index_manipulator manip = {idx.qidx};
my_row_it(QAbstractItemModel* m, int col)
: idx(m ? m->index(0, col) : QModelIndex())
{}
index& operator*() const { return idx; }
my_row_it operator++(int) const
{
auto copy = it;
manip.move(1, 0);
return copy;
}
index_safe_ref my_row_it::operator[](difference_type n) const
{
auto it = it + n; // Operator+ is over there.
return { it.idx };
}
};
【问题讨论】:
标签: c++ iterator random-access temporary-objects