通过引用传递 std::Optional<T> 是否真的可以节省复制?

res*_*net 9 c++ stdoptional

我知道std::optional<T&>标准不支持这一点。这个问题是关于是否通过std::optional<T>&有性能优势

示例代码(https://godbolt.org/z/h56Pj6d6z)复制在这里

#include <ctime>
#include <iomanip>
#include <iostream>
#include <optional>

void DoStuff(std::optional<std::string> str) {
    if (str) std::cout << "cop: " << *str << std::endl;
}

void DoStuffRef(const std::optional<std::string>& str) {
    if (str) std::cout << "ref: " << *str << std::endl;
}

int main() {
    std::optional<std::string> str = {};
    DoStuff(str);
    DoStuffRef(str);
    str = "0123456789012345678901234567890123456789";
    DoStuff(str);
    DoStuffRef(str);
}
Run Code Online (Sandbox Code Playgroud)

(我的实际用例对于复杂的用户定义类型是可选的,但我希望长字符串在编译器方面也能做同样的事情)

在这种情况下,DoStuffRef与 相比,实际上是否节省了任何复制工作DoStuff

我试图查看 godbolt 输出,但我不知道足够的汇编来确定。我确实看到,在 的情况下DoStuff,似乎std::optional<T>创建了一个不存在的临时文件DoStuffRef,所以我怀疑是的,optional通过引用传递一个可以节省一些复制

感谢您的帮助!

yur*_*hek 6

如果你通过了实际考试std::optional<std::string>,那么是的,就不会有副本了。但是,如果您刚刚通过,则std::string必须首先构造临时可选,从而生成字符串的副本。


Jar*_*d42 5

DoStuffRef当参数已经存在时保存额外的副本std::optional<std::string>(如您的示例所示)。

但是,如果您直接传递 a std::string,那么如果这两种情况,std::optional都应该构造 a ,涉及字符串的复制/移动构造函数。