标准C++下能否合法无拷贝为大小对齐兼容的无关数组传递跨类型指针
标准C++框架下异构类型接口的零拷贝流转探讨
免责声明:当前相关内容的探讨以学术研究性质为主。
假设存在我们无法控制、也难以修改源码的外部接口,接口定义如下:
// 外部提供的接口:无法轻松修改 // 向输出缓冲区填充n个float类型数据 void data_source_external(float* pDataOut, size_t n); // 从输入缓冲区读取n个数据字执行发送 void data_sink_external(const uint32_t* pDataIn, size_t n);
请问在标准C++的规范框架下,能否实现两个接口之间的数据零拷贝流转/直通?
也就是说,是否存在合规的实现方式,让下述代码不触发未定义行为(UB),且不需要在两个类型匹配的独立缓冲区之间做数据拷贝:
int main() { constexpr size_t n = 64; float fbuffer[n]; data_source_external(fbuffer, n); // 以下静态断言条件均成立、可在编译期校验 static_assert(sizeof(float) == sizeof(uint32_t), "same size"); static_assert(alignof(float) == alignof(uint32_t), "same alignment"); static_assert(std::numeric_limits<float>::is_iec559 == true, "IEEE 754"); // 以下写法属于明确的UB,是否存在不拷贝数据的合规实现方式? const uint32_t* buffer_alias = static_cast<uint32_t*>(static_cast<void*>(fbuffer)); // 注意: // - reinterpret_cast转换同样属于UB。 data_sink_external(buffer_alias, n); }
据梳理,下述写法至少在严格别名规则层面是属于定义明确的合规行为:
uint32_t ibuffer[n]; std::memcpy(ibuffer, fbuffer, n * sizeof(uint32_t)); data_sink_external(ibuffer, n);
但考虑到ibuffer存储的位模式会与fbuffer完全一致,这类中转拷贝的存在似乎完全冗余。此外,有相关技术讨论提到,优化编译器可能会将这类位完全一致的memcpy操作优化消除,也有Clang 11编译示例初步验证了这一优化能力,需要进一步确认这类实现的合规性与可靠性。
内容的提问来源于stack exchange,提问作者Martin Ba
相关产品推荐
相关产品推荐

