迭代的 "range-based for" 调用是什么
what the "range-based for" call of iteration
我最近想知道如何远程工作,
最后得到如下图:
for(obj& temp_ref:range r)//hide iterator somewhere as the range defined.
对于每次迭代,只有当前对象的更新才能在一个循环中完成工作,这对我来说很不错。
但是当我试图将范围和迭代器组合成一个混合的 class,
我的代码中应该调用哪个运算符++有问题,
从某种意义上说,它应该是在 range-based-for,
中调用派生 class 方法
因为我将对象创建为派生对象,所以我的声明是虚拟的。
这里提供了代码,第一部分比较细,
但是第二个对我来说很奇怪。
#include <iostream>
namespace first
{
template<class iterator>
class range
{
public:
range(iterator ina,iterator inb):a(ina),b(inb){};
iterator a,b;
iterator& begin(){return a;};
iterator& end(){return b;};
};
template<class T>
class iterator
{
public:
iterator(T* ini):i(ini){};
T* i;
virtual iterator<T>& operator= (const iterator<T>& other){this->i=other.i;return *this;};
virtual T& operator* (){return *i;};
virtual T operator!= (const iterator<T>& other){return this->i==other.i?0:1;};
virtual void operator++ (){i++;};
};
class jump2:public iterator<int>
{
public:
jump2(int* ini):iterator<int>(ini){};
virtual void operator++ (){i+=2;};
};
}
namespace second
{
template<class T>
class iterator
{
public:
iterator(T* inStart,T* inFinal):current(inStart),final(inFinal){};
T* current;
T* final;
iterator<T> begin(){return iterator<T>(this->current,this->final);};
iterator<T> end(){return iterator<T>(this->final,this->final);};
virtual iterator<T>& operator= (const iterator<T>& other){this->current=other.current;this->final=other.final;return *this;};
virtual T& operator* (){return *this->current;};
virtual bool operator!= (iterator<T>& other){return this->current!=other.final;};
virtual void operator++ ()
{
std::cout<<"<call base>";
this->current=this->current+1;
};
};
template<class T>
class jumper:public iterator<T>
{
public:
jumper(T* inStart,T* inFinal):iterator<T>(inStart,inFinal){};
void operator++ ()
{
std::cout<<"<call deri>";
this->current=this->current+2;
};
};
};
int main()
{
int a[6]={1,0,2,0,3,0};
//success
{
using namespace first;
range<jump2> a_range(jump2(a),jump2(a+6));
for(int store:a_range)
std::cout<<store<<std::endl;
}//pause();
//Fail
{
using namespace second;
jumper<int> a_iterator_call_jumper(a,a+6);
for(int& i:a_iterator_call_jumper)
std::cout<<i<<std::endl;
}//pause();
return 0;
};
这个输出是
1
2
3
1
<call base>0
<call base>2
<call base>0
<call base>3
<call base>0
<call base>
但应该是
1
2
3
1
<call deri>2
<call deri>3
<call deri>
这个东西出问题是不是我用错了?
或者有一个我还没有找到的错误?
template<class iterator>
class range
{
public:
range(iterator ina,iterator inb):a(ina),b(inb){};
iterator a,b;
iterator& begin(){return a;};
iterator& end(){return b;};
};
没有
template<class iterator>
class range
{
public:
range(iterator ina,iterator inb):a(ina),b(inb){};
iterator a,b;
iterator begin() const {return a;};
iterator end() const {return b;};
};
是的。
template<class T>
class iterator
{
public:
iterator(T* ini):i(ini){};
T* i;
virtual iterator<T>& operator= (const iterator<T>& other){this->i=other.i;return *this;};
virtual T& operator* (){return *i;};
virtual T operator!= (const iterator<T>& other){return this->i==other.i?0:1;};
virtual void operator++ (){i++;};
};
没有
template<class T>
class iterator
{
public:
iterator(T* ini):i(ini){};
T* i;
iterator( iterator const& ) = default;
iterator& operator= (const iterator<T>& other) & = default;
T& operator*() {return *i;};
bool operator!= (const iterator& other) const {return this->i==other.i?0:1;};
void operator++() {++i;};
};
是的。
不要为迭代器使用标准的基于 C++ vtable 的多态对象模型;它们应该是常规类型,基于vtable的多态对象模型是不规则的。
至于second
,不是什么好计划。迭代器和迭代范围不是一回事。将它们粉碎在一起会使您的 class 语无伦次。
C++ 迭代不是为动态分派(多态性)设计的。你可以做到,但它会降低性能,而且编写起来并不容易。您基本上需要将虚拟分派隐藏在常规类型后面(您可以使用 vtables 分派,或者您可以使用 C++ 的基于 void 指针的类型擦除分派)。
如果您习惯了其他语言,许多其他从 C++ 派生出来的语言使用强制引用语义和 class 类型对象的垃圾收集。他们的虚拟继承对象模型适用于引用变量,就像在 C++ 中使用引用和指针类型一样。
C++ 相对古怪(在当今时代),因为它支持将复杂对象作为值类型,并且语言和标准库假定您大部分时间都在使用值类型。 (请注意,指针是一种值类型;但它的值是指针,而不是对象),并且当你想使用 reference/pointer 语义时,你必须调整你的代码。
我最近想知道如何远程工作, 最后得到如下图:
for(obj& temp_ref:range r)//hide iterator somewhere as the range defined.
对于每次迭代,只有当前对象的更新才能在一个循环中完成工作,这对我来说很不错。
但是当我试图将范围和迭代器组合成一个混合的 class,
我的代码中应该调用哪个运算符++有问题,
从某种意义上说,它应该是在 range-based-for,
中调用派生 class 方法
因为我将对象创建为派生对象,所以我的声明是虚拟的。
这里提供了代码,第一部分比较细, 但是第二个对我来说很奇怪。
#include <iostream>
namespace first
{
template<class iterator>
class range
{
public:
range(iterator ina,iterator inb):a(ina),b(inb){};
iterator a,b;
iterator& begin(){return a;};
iterator& end(){return b;};
};
template<class T>
class iterator
{
public:
iterator(T* ini):i(ini){};
T* i;
virtual iterator<T>& operator= (const iterator<T>& other){this->i=other.i;return *this;};
virtual T& operator* (){return *i;};
virtual T operator!= (const iterator<T>& other){return this->i==other.i?0:1;};
virtual void operator++ (){i++;};
};
class jump2:public iterator<int>
{
public:
jump2(int* ini):iterator<int>(ini){};
virtual void operator++ (){i+=2;};
};
}
namespace second
{
template<class T>
class iterator
{
public:
iterator(T* inStart,T* inFinal):current(inStart),final(inFinal){};
T* current;
T* final;
iterator<T> begin(){return iterator<T>(this->current,this->final);};
iterator<T> end(){return iterator<T>(this->final,this->final);};
virtual iterator<T>& operator= (const iterator<T>& other){this->current=other.current;this->final=other.final;return *this;};
virtual T& operator* (){return *this->current;};
virtual bool operator!= (iterator<T>& other){return this->current!=other.final;};
virtual void operator++ ()
{
std::cout<<"<call base>";
this->current=this->current+1;
};
};
template<class T>
class jumper:public iterator<T>
{
public:
jumper(T* inStart,T* inFinal):iterator<T>(inStart,inFinal){};
void operator++ ()
{
std::cout<<"<call deri>";
this->current=this->current+2;
};
};
};
int main()
{
int a[6]={1,0,2,0,3,0};
//success
{
using namespace first;
range<jump2> a_range(jump2(a),jump2(a+6));
for(int store:a_range)
std::cout<<store<<std::endl;
}//pause();
//Fail
{
using namespace second;
jumper<int> a_iterator_call_jumper(a,a+6);
for(int& i:a_iterator_call_jumper)
std::cout<<i<<std::endl;
}//pause();
return 0;
};
这个输出是
1
2
3
1
<call base>0
<call base>2
<call base>0
<call base>3
<call base>0
<call base>
但应该是
1
2
3
1
<call deri>2
<call deri>3
<call deri>
这个东西出问题是不是我用错了?
或者有一个我还没有找到的错误?
template<class iterator>
class range
{
public:
range(iterator ina,iterator inb):a(ina),b(inb){};
iterator a,b;
iterator& begin(){return a;};
iterator& end(){return b;};
};
没有
template<class iterator>
class range
{
public:
range(iterator ina,iterator inb):a(ina),b(inb){};
iterator a,b;
iterator begin() const {return a;};
iterator end() const {return b;};
};
是的。
template<class T>
class iterator
{
public:
iterator(T* ini):i(ini){};
T* i;
virtual iterator<T>& operator= (const iterator<T>& other){this->i=other.i;return *this;};
virtual T& operator* (){return *i;};
virtual T operator!= (const iterator<T>& other){return this->i==other.i?0:1;};
virtual void operator++ (){i++;};
};
没有
template<class T>
class iterator
{
public:
iterator(T* ini):i(ini){};
T* i;
iterator( iterator const& ) = default;
iterator& operator= (const iterator<T>& other) & = default;
T& operator*() {return *i;};
bool operator!= (const iterator& other) const {return this->i==other.i?0:1;};
void operator++() {++i;};
};
是的。
不要为迭代器使用标准的基于 C++ vtable 的多态对象模型;它们应该是常规类型,基于vtable的多态对象模型是不规则的。
至于second
,不是什么好计划。迭代器和迭代范围不是一回事。将它们粉碎在一起会使您的 class 语无伦次。
C++ 迭代不是为动态分派(多态性)设计的。你可以做到,但它会降低性能,而且编写起来并不容易。您基本上需要将虚拟分派隐藏在常规类型后面(您可以使用 vtables 分派,或者您可以使用 C++ 的基于 void 指针的类型擦除分派)。
如果您习惯了其他语言,许多其他从 C++ 派生出来的语言使用强制引用语义和 class 类型对象的垃圾收集。他们的虚拟继承对象模型适用于引用变量,就像在 C++ 中使用引用和指针类型一样。
C++ 相对古怪(在当今时代),因为它支持将复杂对象作为值类型,并且语言和标准库假定您大部分时间都在使用值类型。 (请注意,指针是一种值类型;但它的值是指针,而不是对象),并且当你想使用 reference/pointer 语义时,你必须调整你的代码。