【问题标题】:Getting a Raw Pointer to the end of a Container获取指向容器末尾的原始指针
【发布时间】:2015-08-18 13:22:46
【问题描述】:

如果我有一个容器的enditerator,但我想获得一个指向它的原始指针,有没有办法做到这一点?

假设我有一个容器:foo。例如,我不能这样做:&*foo.end(),因为它会产生运行时错误:

向量迭代器不可解引用

我可以做到这一点,但我希望有一种更清洁的方式到达那里:&*foo.begin() + foo.size()

编辑:

这不是关于如何将迭代器转换为一般指针的问题(显然这是问题所在),而是如何专门将结束迭代器转换为指针。 "duplicate" question 中的答案实际上建议取消引用迭代器。结束迭代器不能在没有段错误的情况下被取消引用。

【问题讨论】:

  • &*foo.end() 无论如何都没有意义,因为end() 是容器的最后一个 元素之后的元素的迭代器,试图访问它会调用UB。
  • 您是在询问一般的容器,还是专门询问vector?正如 LRiO 所说,它甚至没有一般意义。结束迭代器不一定“指向”任何东西,那么指向该位置的指针甚至意味着什么?对于forward_list,结束迭代器通常是一个空指针,因此对于所有列表都是相同的,对于std::list,它指向一个特殊的标记,而不是value_type 的元素。
  • @JonathanWakely 我正在尝试完成这样的事情:stackoverflow.com/a/32073224/2642059 所以我需要从end 获得char*
  • @SingerOfTheFall 我正在尝试完成这样的事情:stackoverflow.com/a/32073224/2642059 所以我需要从end 获得char*
  • 那么你应该将大小添加到第一个元素的地址,我不知道你为什么认为这不干净。如果您有一个将其数据存储在连续数组中的容器,那么指针算法就是正确的方法。

标签: c++ pointers iterator segmentation-fault containers


【解决方案1】:

访问存储结束的正确方法是:

v.data() + v.size()

这是因为v为空时*v.begin()无效。

为所有连续容器(vectorstringarray)提供成员函数 data

从 C++17 开始,您还可以使用非成员函数:

data(v) + size(v)

这也适用于原始数组。

【讨论】:

    【解决方案2】:

    一般?没有。

    而你所问的事实表明你的整体设计有问题。


    对于向量、数组、字符串?当然……但是为什么呢?

    只需获取一个指向有效元素的指针,然后推进它:

    std::vector<T> foo;
    const T* ptr = foo.data() + foo.size();
    

    只要您不取消引用这样的指针(这几乎等同于取消引用迭代器,就像您在尝试中所做的那样),获取并持有这样的指针是有效的,因为它指向特殊的 -结束位置。

    请注意,如果向量为空,&amp;foo[0] + foo.size() 的行为未定义,因为 &amp;foo[0]&amp;*(foo.data() + 0)&amp;*foo.data(),并且(就像您的尝试一样)如果那里什么都没有,*foo.data() 是不允许的.所以我们避免了所有的取消引用,只是简单地推进 foo.data() 本身。

    无论如何,这仅适用于向量1、数组和字符串的情况。其他容器不保证(或可以合理预期提供)存储连续性;它们的结束指针几乎可以是任何东西,例如一个“哨兵”空指针,它对你没有任何用处。

    这就是迭代器抽象首先存在的原因。如果可以的话,坚持下去,而不是深入研究原始指针的使用。


    1.std::vector&lt;bool&gt; 除外。

    【讨论】:

    • "这只适用于向量的情况" ...和std::arraystd::basic_string(三种类型的连续容器在最近的草案中定义)。
    • @JonathanWakely:哦,字符串最终被视为“容器”?不错。
    • 如果你眯着眼睛正好是的,:) 第 21 条说 basic_string 现在是一个连续的容器。
    • @JonathanWakely:是时候了:P
    • @LightnessRacesinOrbit 这个“为什么”可能有很多很好的答案。一个好的答案是this :)
    猜你喜欢
    • 2011-06-13
    • 2013-04-01
    • 2014-04-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2018-06-01
    • 2011-09-23
    • 1970-01-01
    相关资源
    最近更新 更多