传递std::optional<T>引用是否真的能节省拷贝开销?
结论
DoStuffRef 相比 DoStuff 确实可以减少拷贝开销,你的猜测完全正确。
具体原理说明
你提供的示例代码中,两种函数仅参数传递方式存在差异:
// 按值传递,会触发optional拷贝 void DoStuff(std::optional<std::string> str) { if (str) std::cout << "cop: " << *str << std::endl; } // 按const引用传递,无额外拷贝 void DoStuffRef(const std::optional<std::string>& str) { if (str) std::cout << "ref: " << *str << std::endl; }
二者的开销差异可以从以下几点理解:
- 按值传递
std::optional<T>的开销逻辑:
调用DoStuff(str)时,形参是实参的完整拷贝副本,会触发std::optional的拷贝构造函数:- 如果
optional为空,仅需要拷贝optional内部的状态标记位和类型占位内存,开销虽小但仍高于传引用 - 如果
optional持有有效值,还会额外调用内部T的拷贝构造函数,你示例中的长字符串如果超出小字符串优化(SSO)阈值,还会触发堆内存分配和数据拷贝,这部分开销非常高。
- 如果
- 按
const std::optional<T>&传递的开销逻辑:
引用本质是原对象的别名,底层仅传递原对象的内存地址,全程不会触发optional本身和内部持有对象的任何拷贝操作,开销固定为一次指针传递,远低于按值传递的成本。 - 你观察到的汇编现象对应逻辑:
你看到的DoStuff独有的临时对象生成逻辑,正是拷贝构造新std::optional实例的过程,DoStuffRef没有这部分逻辑,自然没有对应的拷贝开销。 - 针对复杂自定义类型场景:
如果optional包装的是拷贝开销远高于std::string的自定义类型,按引用传递的性能优势会更明显,因为它完全避免了内部复杂对象的拷贝成本。
内容的提问来源于stack exchange,提问作者resnet
相关产品推荐
相关产品推荐

