【问题标题】:Understanding .begin and .end in vectors理解向量中的 .begin 和 .end
【发布时间】:2020-01-22 19:54:50
【问题描述】:

我正在从 this post 学习向量,它们从迭代器开始。他们定义 .begin 和 .end 如下:

begin() – 返回指向向量中第一个元素的迭代器

end() – 返回一个指向理论元素的迭代器 跟随向量中的最后一个元素

然后他们给出以下代码 sn-p,我添加了第三个 for 循环来表达我的问题。

#include<iostream>
#include<vector>

int main() {
    std::vector <int> g1; //creating a vector
    for (int i = 1; i <= 3; i++){
        g1.push_back(i);
    }
    std::cout << "Output of beginning and end values: ";
    for (auto i = g1.begin(); i != g1.end(); i++) {
        std::cout << *i << " "; 
    }
    std::cout << "\nOutput of beginning and end addresses: ";
    for (auto i = g1.begin(); i != g1.end(); i++) {
        std::cout << &i << " ";
    }
     //"Output of beginning and end values: 1 2 3"
     //"Output of beginning and end addresses: 0105FB0C 0105FB0C 0105FB0C"
    return 0;
}

我的困惑是i 的地址保持不变,但i 的值已经改变。 i* 不意味着 i 只是被取消引用了吗?因此,如果i 的地址没有改变,则必须改变它的值,以便它能够具有不同的值。我想我可能会将迭代器与指针混淆。我知道auto 基本上是类型推断,但仅此而已。

所以我的问题是,如果向量中每个元素的地址都相同,i 的值如何变化?

【问题讨论】:

  • i 是一个迭代器,它“像”一个指针。它包含某种句柄(可以是指针,也可以是索引),可用于 (a) 在集合中移动和 (b) 定位集合的当前元素。如果您在第一个循环中查看g1[i]&amp;i,您还会有同样的问题吗?如果不是,为什么?
  • 想象一下,如果i 只是一个int*。它可能有助于了解正在发生的事情。请注意,与其他容器不同,T*std::vector&lt;T&gt; 的有效迭代器类型,因此比较非常准确。
  • "因此,如果i 的地址没有改变,则必须更改其值,以便它能够具有不同的值" - 那就是i++ 循环中的语句。它使迭代器前进以引用向量中的下一个元素

标签: c++ vector auto


【解决方案1】:

&amp;i是局部变量i的地址。这不会改变。 *i 取消对迭代器的引用,并返回向量中该元素的值。 &amp;*i 将返回一个指向向量中元素的指针。

所以你应该循环使用

std::cout << &*i << " ";

查看地址变化。

【讨论】:

  • 谢谢!我看到地址发生了变化,但它们相隔 4 个字节。即 00F6E3B8 00F6E3BC 00F6E3C0。是不是因为ìnt默认占用4个字节?
  • @S.Ramjit 是的,int 在您的系统上是 4 个字节。其他系统可能有不同的大小。
【解决方案2】:

为了更清楚,请考虑类似的代码,但使用数组代替向量。

#include <iostream>
#include <iterator>

int main() 
{
    int a[] = { 1, 2, 3 };

    for ( auto p = std::begin( a ); p != std::end( a ); p++ )
    {
        std::cout << "The address of p is " << &p
                  << ", its value is " << p
                  << ", and the pointed value is " << *p
                  << '\n';
    }

    return 0;
}

程序输出可能看起来像

The address of p is 0x7ffcaf6a6830, its value is 0x7ffcaf6a683c, and the pointed value is 1
The address of p is 0x7ffcaf6a6830, its value is 0x7ffcaf6a6840, and the pointed value is 2
The address of p is 0x7ffcaf6a6830, its value is 0x7ffcaf6a6844, and the pointed value is 3

这部分输出的字符串

The address of p is 0x7ffcaf6a6830

没有被改变,因为它是局部变量(指针)p本身的地址。

这部分字符串

its value is 0x7ffcaf6a683c

正在更改,因为在循环中指针的值已更改

for ( auto p = std::begin( a ); p != std::end( a ); p++ )
                                                        ^^^^

在每次迭代中,指针都指向数组的下一个元素。

这部分字符串

and the pointed value is 1

也正在更改,因为由于取消引用指针而输出了指向的值。

向量的迭代器也会发生同样的事情。

【讨论】:

    【解决方案3】:

    我想我可能把迭代器和指针混淆了

    嗯,指针是迭代器,所以这是可以理解的。但并非所有迭代器都是指针。也就是说,非指针也可以是迭代器。

    我知道 auto 基本上是类型推断,但仅此而已。

    在这种情况下,类型被推断为std::vector&lt;int&gt;::iterator,因为这是std::vector&lt;int&gt;::begin 返回的类型。

    所以我的问题是,如果向量中每个元素的地址都相同,i 的值如何变化?

    i 的值被循环中的i++ 更改。存储对象的地址在对象的生命周期内永远不会改变。无论该对象的类型是指针、其他迭代器还是根本不是迭代器。

    【讨论】:

      猜你喜欢
      • 2019-05-18
      • 1970-01-01
      • 1970-01-01
      • 2014-03-18
      • 2013-07-21
      • 2013-09-06
      • 1970-01-01
      • 1970-01-01
      • 2021-09-02
      相关资源
      最近更新 更多