为何C++编译器无法在RVO下省略POD移入optional的移动操作?
为什么std::optional包装大型POD时编译器无法省略memcpy?
先看这段代码:
#include <optional> #include <array> struct LargeType { std::array<int, 256> largeContents; }; LargeType doSomething(); std::optional<LargeType> wrapIntoOptional(){ return std::optional<LargeType> {doSomething()}; }
这里doSomething()返回一个大型POD对象,wrapIntoOptional()的作用是把这个对象包装成std::optional<LargeType>返回。但编译后会发现,编译器生成了memcpy指令,没办法完全省略对象的移动操作。
我知道C++的as-if规则允许省略这类无副作用的移动,但为什么编译器做不到?
我原本的思路是:编译器可以把std::optional内部的存储位置以引用形式传递给doSomething()(这类大型对象通常会通过隐藏引用返回)。因为RVO的存在,std::optional本身已经在wrapIntoOptional()调用者的栈上,而且std::optional的构造函数是头文件里的内联实现,编译器能拿到完整定义,理论上应该可以直接让doSomething()把对象构造到std::optional的内部存储里,从而避免memcpy。这个想法哪里有问题?
注:我不是说C++标准要求编译器必须做这个优化,只是觉得这是合理的优化方向,而且包装对象到std::optional是很常见的操作,现代编译器应该已经支持才对。
内容的提问来源于stack exchange,提问作者gexicide
相关产品推荐
相关产品推荐

