让B源自A类。通过阅读各种文章,我给人一种像这样的印象
const std::shared_ptr<const A> a(new B());
const std::shared_ptr<const B>& b = reinterpret_cast<const std::shared_ptr<const B>&>(a);
出于某些原因,不鼓励使用,而应该使用reinterpret_pointer_cast。但是,出于性能原因,我想避免创建新的shared_ptr。上面的代码合法吗?是否会导致不确定的行为?它似乎可以在gcc和Visual Studio中使用。
答案 0 :(得分:1)
const std::shared_ptr<const A> a(new B());
const std::shared_ptr<const B> b = std::static_pointer_cast<const B>(a);
我非常怀疑上述内容是否会导致性能问题。但是,如果您有证据表明shared_ptr会导致性能问题,请回退到原始指针:
const B* pB = static_cast<const B*>(a.get());
另一个提示。请尝试避免在具有继承关系的类之间使用reinterpret_cast
。在存在虚拟方法和/或多重继承的情况下,static_cast
将正确地将指针偏移调整为正确的vtable或基本偏移。但是reinterpret_cast
不会。 (或者从技术上说:未定义的行为)
答案 1 :(得分:0)
reinterpret_cast
通常会导致UB。有时出于性能考虑,您愿意冒险使用它,但是您将尽力避免这种情况。在这种情况下,最好使用static_pointer_cast
。
请注意,即使在这种情况下,即使您不知道可以使用其他演员表,并且愿意冒险使用reinterpret_cast
,也必须在演员表转换前后使用一些验证-否则您将得到很多错误,并花费大量时间。
答案 2 :(得分:0)
首先,创建类型为a
的对象const std::shared_ptr<const A> a
,并使用指向某个类型B
的指针对其进行初始化。仅当您可以将B*
分配给A*
时,此方法才有效,因此应该存在诸如继承之类的关系。忽略这一点,您可以使用reinterpret_cast将某种类型的对象转换为对另一种类型的引用:
可以将类型T1的glvalue表达式强制转换为“对...的引用 T2”(如果可以明确表示“指向T1的指针”类型的表达式) 使用reinterpret_cast转换为“ T2的指针”类型 结果指向与源glvalue相同的对象,但是带有 指定的类型。 [注意:也就是说,对于左值,参考类型转换 reinterpret_cast(x)与转换具有相同的效果 带有内置&和*运算符的* reinterpret_cast(&x)(对于reinterpret_cast(x)同样)。 —尾注]
对于指针,reinterpret_cast归结为转换为void*
,然后转换为目标类型:
对象指针可以显式转换为的对象指针 72当对象指针类型的prvalue v为 转换为对象指针类型“ pointer to cv T”,结果是
static_cast<cv T*>(static_cast<cv void*>(v))
。
两个静态强制类型转换的语义定义为:
“指针指向cv1无效”类型的prvalue可以转换为prvalue 类型为“指向cv2 T的指针”,其中T是对象类型,而cv2是 与cv1相同或更高的cv资格。的 空指针值将转换为 目标类型。如果原始指针值代表地址 内存中一个字节的A和A满足T的对齐要求, 然后结果指针值表示与 原始指针值,即A。任何其他类似结果 指针转换未指定。
我正在工作的平台具有16或32位的近和远指针。在这种情况下,类型shared_ptr<A>
和shared_ptr<B>
具有不同的大小和对齐方式,因此将一种类型转换为另一种类型是不确定的行为。如果对齐方式匹配,则定义静态转换的结果。
但是,关于reinterpret_cast到引用的第一条款也包含一个注释
[ Note: That is, for lvalues, a reference cast reinterpret_cast<T&>(x) has the same effect as the conversion *reinterpret_cast<T*>(&x) with the built-in & and * operators (and similarly for reinterpret_cast<T&&>(x)). —end note ]
因此,基本上,强制转换在语义上与具有立即取消引用的指针转换相同。即使指针具有相同的大小(并且兼容的对齐方式),使用强制转换的指针也会违反严格的别名规则,因为取消引用是一种访问。
如果程序尝试访问对象的存储值 透过其中之一以外的视线 以下类型的行为未定义:53 —对象的动态类型, —对象的动态类型的cv限定版本, —与对象的动态类型类似的类型(定义见4.4), —一种类型,它是与对象的动态类型相对应的有符号或无符号类型, —是与动态类型的CV限定版本相对应的有符号或无符号类型的类型 对象的 —集合或联合类型,在其元素中包括上述类型之一或非静态 数据成员(包括递归地包括子聚合的元素或非静态数据成员) 或包含工会)
答案 3 :(得分:0)
仅在调用传递给函数的类型的类的函数(包括成员函数)(包括隐式{时)时,定义shared_ptr
或任何其他标准类或模板的功能{1}}参数):
标准中没有任何内容定义了对于任意两个标准类型this
和调用Foo
并传递Bar
的标准函数时发生的情况Foo
(甚至适用于用户类型)。
这是未定义的;是 un 定义的。不满足最基本的先决条件:使用正确类型的参数。