【问题标题】:Why does static_cast still work with null pointers in spite of slicing?尽管切片,为什么 static_cast 仍然可以使用空指针?
【发布时间】:2012-06-09 14:27:06
【问题描述】:

如果我们使用多重继承,切片将使父对象的地址与叶对象的地址不同:

struct X {int x};
struct Y {int y};
struct Z : X, Y {int z};

所以如果我们有一个Z 对象z,它的地址&z与其父Y 的地址重合:static_cast<Y*>(&z) 比@ 高四个字节987654327@.

static_cast 的好处在于它是静态的,因此不占用运行时间(与 dynamic_cast 相比)。 但是,如果我们有一个指向0Z*,那么每次转换到父级时都应该并且确实 产生一个空指针。 为什么这个工作以及它是如何实施的?这是否意味着每个static_cast 都会引入一个分支指令?

【问题讨论】:

  • 这是可行的,因为Z 类型的每个对象也是Y 类型的对象。基类的指针可以隐式指向派生类的对象。
  • @Als:我说的是static_cast的实现。当然每个Z 都包含一个Y,但它们的地址不同。但是,您可能会注意到 static_cast<Y*>(zPtr)0 如果 zPtr0
  • “它是静态的,所以不占用运行时间”——嗯?您确实意识到 static_cast 也可以在不同大小的整数之间进行转换,不是吗?这也不是(通常)在运行时无操作。
  • @hvd:啊,是的。我在想“与需要 rtti 的 dynamic_cast 相比”。
  • 啊,这清楚了。但是dynamic_cast 并不总是需要 RTTI:至少在 GCC 中,dynamic_cast<void*> 甚至可以与 fno-rtti 一起使用。

标签: c++ casting null static-cast object-slicing


【解决方案1】:

是的,从指向派生类的指针到指向基类的指针的隐式转换以及再次返回 static_cast 都必须保留空指针值。这意味着对于基类地址与派生类地址不一致的多重继承情况,生成的代码中通常需要一个分支。

理论上,实现可以在“零”地址周围保留一系列地址来表示空指针并避免在这种情况下分支,但其代价是增加了对空指针比较的额外检查。

【讨论】:

  • but it would be at the expense of adding extra checking for comparisons of null pointers 这是一个比 static_casting 更常见的场景。
  • @nightcracker:当然。我无法想象使用这种策略的实际实现;这更像是一种思想练习。
  • @CharlesBailey:但请注意,很多实现确实实际上无论如何都会保留接近零的地址。例如,在 Windows 上,前 4 兆字节的地址空间始终是“空的”——您可以形成这样的地址,但尝试取消引用它会使您的程序中止。
猜你喜欢
  • 2014-12-04
  • 1970-01-01
  • 1970-01-01
  • 2019-01-03
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2013-11-07
  • 2012-10-23
相关资源
最近更新 更多