为何pointer_cast替代C风格转换给CMapStringToPtr::Lookup传参会失败
问题根因
你遇到的问题核心是自定义pointer_cast的返回值是右值临时对象,无法正确匹配CMapStringToPtr::Lookup的第二个参数要求。
CMapStringToPtr::Lookup的第二个参数是void*&类型的非常量左值引用,作用是把查询到的指针结果写入传入的变量:
- 原来的C风格强转
(void*&)psEvent是直接对psEvent本身做类型重解释,相当于给SPECIAL_EVENT_S*类型的psEvent取了一个void*类型的别名,Lookup写入时直接修改的是psEvent本身的取值,逻辑正常。 - 你自定义的
pointer_cast是按值返回,返回的void*&实际是临时右值对象,即使微软编译器的非标准扩展允许临时值绑定到非常量左值引用(所以编译无报错),Lookup写入的也只是这个临时对象,原psEvent的取值完全没有被修改,自然后续判断为空,无法进入分支。
现代规范写法
优先用更安全、无歧义的显式临时变量接收写法,避免对指针引用做强制转换:
void* pLookupBuf = nullptr; // 无需强转,直接传入void*类型变量接收查询结果 if (m_pMapSPtrEvents->Lookup(strKey, pLookupBuf)) { // 从void*转回实际类型用static_cast即可,比reinterpret_cast更安全 auto* psEvent = static_cast<SPECIAL_EVENT_S*>(pLookupBuf); if (psEvent != nullptr) { bActivate = TRUE; strTipText = psEvent->strEvent; } }
这种写法完全符合C++标准,没有任何未定义行为,可读性也更高。
如果希望沿用原来的写法风格,不新增临时变量,可以直接用标准C++的reinterpret_cast做引用转换,不需要用自定义的pointer_cast:
if (m_pMapSPtrEvents->Lookup(strKey, reinterpret_cast<void*&>(psEvent)))
reinterpret_cast转换左值引用时返回的是左值,可以正常绑定到Lookup的非常量左值引用参数,效果和原来的C风格强转完全一致,同时比C风格强转更易识别、更符合现代C++规范。
去掉&后编译报错的原因
去掉&后pointer_cast返回的是void*类型的右值,而Lookup要求参数是可修改的void*&左值引用,右值无法绑定到该类型参数,因此编译失败。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

