调用成员函数.begin()
of std::vector
and std::begin()
右值会导致不同的输出,如以下测试所示:
vector<int> a{ 1, 2, 3 };
vector<int>::iterator it1 = move(a).begin(); // OK
vector<int>::const_iterator it2 = move(a).begin(); // OK
vector<int>::iterator it3 = begin(move(a)); // Error!
vector<int>::const_iterator it4 = begin(move(a)); // OK
这是我的理解:std::begin()
calls const&
过载(因为它缺乏&&
过载),因此,它返回一个const_iterator
目的。所以,返回值可以赋值给const_iterator
但不是iterator.
- 我的理解正确吗?
- 为什么
std::begin()
没有右值重载?
只是我用过的一个笔记move(a)
演示调用.begin()
and std::begin()
关于右值。当然,它可以被任何右值对象替换.begin()
and std::begin()
都有明确的定义。
Edit:这是我在哪里遇到这个问题的真实例子。我已经简化了很多只是为了传达这个想法std::begin()
在右值上调用。所以,自从row_matrix
是一个代理类,调用应该没有问题begin
and end
由于底层对象是相同的,因此在右值上。
class matrix_row;
class row_iterator;
class matrix {
public:
matrix_row row(int i);
// other members
};
class matrix_row { // <- proxy class representing a row of matrix
public:
row_iterator begin();
row_iterator end();
// other members
private:
int row_;
matrix& matrix_;
};
class row_iterator {
// defined everything needed to qualify as a valid iterator
};
matrix m(3,4);
for(auto x = m.row(1).begin(); x != m.row(1).end(); ++x) {
*x /=2; // OK
}
for(auto x = begin(m.row(1)); x != end(m.row(1)); ++x) {
*x /= 2; // Error
}
直到最近,超载.begin()
通过调用对象的右值/左值是不可能的。
添加它后,将此类更改改造到标准库中理论上可能会破坏现有代码。
破坏现有代码是很糟糕的,糟糕到足以留下遗留的怪癖,除非有相当有力的证据表明此类代码不存在,会有明确的诊断,和/或更改的效果确实有用。
So .begin()
忽略了其右价值*this
.
没有这样的限制std::begin
,除了可能希望与.begin()
.
理论上,标准容器对被调用没有正确的响应std::begin
在右值上下文中。 “正确”的互动方式std::move
或右值是您不应该关心调用完成后移出对象的状态。
这意味着(逻辑上)您只能获取两个迭代器之一(开始或结束)。
在这种情况下,正确的语义是什么是一个很大的困惑。我编写了适配器,在这种情况下(例如,对右值的伪开始/结束调用)生成移动迭代器,但这样做通常非常令人惊讶,我认为这最终是一个糟糕的举动。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)