【问题标题】:reinterpret_cast an iterator to a pointerreinterpret_cast 指向指针的迭代器
【发布时间】:2013-10-24 15:12:14
【问题描述】:

我有一个 Things 的迭代器。如果我想将当前项目转换为指向该项目的指针,为什么会这样:

thing_pointer = &(*it);

但这不是:

thing_pointer = reinterpret_cast<Thing*>(it);

这是我试图理解的编译器错误:http://msdn.microsoft.com/en-us/library/sy5tsf8z(v=vs.90).aspx

以防万一,迭代器的类型是std::_Vector_iterator&lt;std::_Vector_val&lt;Thing,std::allocator&lt;Thing&gt; &gt; &gt;

【问题讨论】:

  • 为什么reinterpret_cast 会起作用?您可能对 reinterpret_cast 是什么有一个错误的概念,或者问题可能在于运算符重载和迭代器类型中的 operator*

标签: c++ iterator reinterpret-cast


【解决方案1】:

&(*it);

*重载 以执行您在逻辑上的意思:将迭代器类型转换为其指向的对象。然后,您可以安全地获取此对象的地址。

而在

reinterpret_cast<Thing*>(it);

您是在告诉编译器将it 对象重新解释为指针。但它可能根本不是一个指针——它可能是一个 50 字节的结构,就你所知!在这种情况下,它的第一个 sizeof (Thing*) 字节绝对不会碰巧指向任何有意义的东西。

提示:reinterpret_cast&lt;&gt; 几乎总是错误的。

【讨论】:

  • 您说的是这个,但我只是想为读者澄清一下:it 不是(必然)一个指针——它是一个对象。一个恰好模拟指针的对象。
  • 谢谢。我刚刚在玩 reinterpet_cast 因为我假设迭代器是一个指针,这就是为什么我希望它是一个等效的操作。我很高兴我这样做了,否则我仍然会有这样的假设!
【解决方案2】:

强制性标准报价,强调我的:

5.2.19 重新解释演员表

1/ [...] 可以使用显式执行的转换 下面列出了 reinterpret_cast。 无法进行其他转换 使用 reinterpret_cast 显式执行。

4/ 指针可以显式转换为任何整数类型 large 足以容纳它。 [...]

5/ 整数类型或枚举类型的值可以显式 转换为指针。 [...]

6/ 函数指针可以显式转换为函数 不同类型的指针。 [...]

7/ 对象指针可以显式转换为对象指针 不同类型的。 [...]

8/ 将函数指针转换为对象指针类型,反之亦然 反之亦然是有条件的。 [...]

9/ 将空指针值(4.10)转换为空指针 目标类型的值。 [...]

10/ [...] “指向 T1 类型 X 成员的指针” 可以显式 转换为 [...] “指向 T2 类型 Y 成员的指针” [...]

11/ A [...] T1 可以转换为类型“引用 T2”,如果 “指向 T1 的指针”类型的表达式可以显式转换为 使用 reinterpret_cast 键入“指向 T2 的指针”。 [...]

除了 4/、5/ 和 11/ 中提到的整数到指针和值到引用的转换之外,唯一可以使用 reinterpret_cast 执行的转换是指针到指针的转换。

但是在:

thing_pointer = reinterpret_cast<Thing*>(it);

it 不是一个指针,而是一个对象。碰巧这个对象被设计成在很多方面模拟一个指针,但它仍然不是一个指针。

【讨论】:

  • 谢谢。我(天真地)假设 reinterpret_cast 只会投射任何东西,即使它没有意义。显然不是。
  • @AdamMillerchip:不,尽管它会盲目地将几乎任何指针转换为任何其他指针,即使它没有任何意义。请注意以下几点:首先,castconversion 之间存在差异。前者告诉编译器假装某物实际上是其他东西,而后者告诉编译器从其他东西创建一个新事物。其次,正如其他地方所提到的,在极少数情况下使用reinterpret_cast 是可取的或正确的。通常这是错误的事情。
  • @AdamMillerchip:还请注意,reinterpret_cast 不仅不会保护您免受未定义行为的影响,它实际上还可以为未定义行为创造更多潜力,因为您正在超越 C++ 的类型安全系统并且把事情掌握在自己手中。
【解决方案3】:
  1. 因为迭代器的* 运算符重载,它返回一个 引用它指向的对象。
  2. 你可以通过thing_pointer = *(reinterpret_cast&lt;Thing**&gt;(&amp;it));强制它。但这是未定义的行为。

【讨论】:

  • 我会对该答案的版本 +1,其中缺少第 (2) 点。但是(2)仅在您碰巧使用 发生 的 C++ 标准库的实现以这种方式在内部表示迭代器时才有效,但它很可能不会,所以您绝对不应该靠这个!
  • 这就是为什么会有“但这是未定义的行为”。在答案中。我只是展示了它应该如何编写为可编译的。
  • 好的,但是我认为从您编写它的方式来看,这仍然不是很明显的错误做法,即使它使编译成功。毕竟,如果目标只是让编译成功,而语义根本不重要,那么您同样可以用空语句; 替换整个语句:-P
【解决方案4】:

因为迭代器不是指针。它是一个实现定义的结构类,如果你试图将它重新解释为一个指针,迭代器类的原始数据将被当作一个内存指针,它可能但可能不会指向有效内存

【讨论】:

    【解决方案5】:

    首先获取对象的引用,然后获取对象的地址,给出指针。

    第二个尝试将迭代器转换为指针,这可能会失败,因为大多数类型不能转换为指针 - 只有其他指针、整数和具有转换运算符的类类型。

    【讨论】:

      猜你喜欢
      • 2018-09-04
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      • 2014-10-13
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      • 2014-10-31
      相关资源
      最近更新 更多