![](/img/trans.png)
[英]Accessing a method of a class object stored in a vector using an Iterator. How?
[英]C++ - Using array/pointers in vector (or other container) constructor that expects type Iterator. How is that possible?
下面的文字来自C ++在线课程。 它说vector
类的构造函数
template <class InputIterator>
vector ( InputIterator first, InputIterator last, const Allocator& = Allocator() );
可以接收指针作为第一个( InputIterator first
)和第二个参数( InputIterator last
)。
下一个构造函数使用迭代器进行初始化。 它将创建一个向量,该向量具有从第一个(包含)到最后一个(不含)的值的副本。 在最典型的情况下,此构造函数使用现有集合中的元素创建新的向量。 但是由于将迭代器定义为一组操作而不是某种类型的事实,因此也可以使用普通指针。 此评论得出一个结论,您可以使用普通的C ++数组初始化集合。 实际上,您可以。
#include <vector>
#include <iostream>
using namespace std;
int main()
{
int a1[]={1,2,3,4,5,6,7,8,9,10};
//first one
vector<int> v1(a1, a1+10);
cout<<"Size (v1): "<<v1.size()<<endl;
for(unsigned i = 0; i < v1.size(); ++i)
{
cout<< v1[i]<<" ";
}
cout<<endl;
//second one;
vector<int> v2(a1+5,a1+10);
cout<<"Size (v2): "<<v2.size()<<endl;
for(unsigned i = 0; i < v2.size(); ++i)
{
cout<< v2[i]<<" ";
}
cout<<endl;
return 0;
}
我可以习惯这一点,但是我真的不明白为什么有这种可能。 我想了解这项技术。
在这种情况下(请参见代码),我的问题是,我怎么可能只简单地放置一个数组地址而不是一个迭代器?
在上面的代码中,将一个int *
类型的元素作为InputIterator
类型的参数。 这使我感到困惑。
所有的故事都是关于构造对迭代器的期望。 它期望能够增加它(使用++),以尊重它(使用*)。 插入器既可以是重载++和*运算符的类,也可以是自然支持这两种操作的基本指针类型。
实际上,C ++迭代器经过了精心设计,以概括指针的语义并模仿其语法(因此, operator*
重载)。
请参阅原始SGI文档中的一般性讨论或此处的最新C ++版本的处理,并特别注意:
std::vector
构造函数仅需要InputIterator 如果您真的不相信#1,那么您可能还希望看到标准库显式地为原始指针提供迭代器特征 ,并且如果您仍在苦苦挣扎,请看一下构造函数的实现,以及请放心,针对其参数的所有操作格式都正确。
要回答最后一个问题,指针指向内存中的位置。 由于存储器是随机访问的,因此指针可以归类为具有随机访问的指针。 迭代器具有相同的分类类型。 cplusplus.com的布局很好,可以显示此处支持哪种类型的迭代器。 这样,我们可以看到输入迭代器是最低的类型,并且它们可以执行最少的操作。 由于指针与随机访问迭代器相同,并且随机访问迭代器可以执行输入迭代器可以执行的所有操作,因此没有任何问题。
如果这是相反的方法,并且您有一个需要随机访问迭代器的函数,并且提供了前向迭代器,则不能保证代码会正常工作。 这是因为该函数可能依赖于某个操作,而随机访问迭代器可以执行此操作,而正向迭代器则无法执行。
通常,当您编写这种类型的代码并指定所需的迭代器类型时,可以指定允许代码编译的最小类型。 只是打印内容的东西只需要一个正向迭代器,因为您只是遍历需要随机访问的内容时。
因为数组将其元素存储在连续内存中。 因此,如果您知道类型的大小以及第一个元素的指针,则可以找出所有其余元素的地址。
int values[10];
&values[5] == &values[0] + 5 // due to pointer arithmetic
§5.7加法运算符
加法运算符+和-从左到右分组。 通常对算术或枚举类型的操作数执行算术转换。
另外 ,两个操作数都应具有算术或无作用域枚举类型,或者一个操作数应是指向完全定义的对象类型的指针 , 另一个操作数应具有整数或无作用域的枚举类型 。
对于减法,应满足下列条件之一:
—两个操作数都具有算术或非范围枚举类型; 要么
—两个操作数都是相同完全定义对象类型的cv限定或cv非限定版本的指针; 要么
—左操作数是指向完全定义的对象类型的指针,而右操作数具有整数或无作用域的枚举类型。...
当将具有整数类型的表达式添加到指针或从指针中减去时,结果将具有指针操作数的类型。 如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向与原始元素偏移的元素,以使结果数组元素和原始数组元素的下标之差等于整数表达式 。 换句话说,如果表达式P指向数组对象的第i个元素,则表达式(P)+ N(相当于N +(P))和(P)-N(其中N的值为n)表示分别存在于数组对象的第i + n个元素和第i-n个元素中,前提是它们存在。 此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向数组对象的最后一个元素之后,如果表达式Q指向数组对象的最后一个元素之后,表达式(Q)-1指向数组对象的最后一个元素。 如果指针操作数和结果都指向同一数组对象的元素,或者指向数组对象的最后一个元素,则求值不会产生溢出; 否则,行为是不确定的。
因此,基本上,该标准定义了指针T*
和整数类型之间的算术
T* t + n // where n is an offset (of integral type)
从初始t
得出另一个n * sizeof(T)
T*
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.