std::可选参数会创建副本吗?

Does an std::optional parameter create a copy?

本文关键字:副本 创建 参数 std      更新时间:2023-10-16

我有一个函数,它需要一个std::optional。

void foo(const std::optional<T>& opt);

但是复制T是多余的。

这会创建T的副本吗?

如果是这样,我怎么不能不创建副本?

正如您的后续评论所澄清的那样,您foo调用函数,如下所示:

T t;
...
foo({t});

在这种情况下,答案是肯定的。将创建t的副本。为避免这种情况,您可以使用std::reference_wrapper来避免复制:

void foo(const std::optional<std::reference_wrapper<const T>> &optT) {
...
}

通过对函数进行这些更改,以相同的方式调用它不会导致创建副本。

是的,std::optional 存储您传递给它的任何内容的副本。C++17 标准明确禁止在 std::optional 中存储引用。请参阅:https://en.cppreference.com/w/cpp/utility/optional#:~:text=There%20are%20no%20optional%20references

正如其他人所建议的那样,传递std::optional<std::reference_wrapper<const T>>是避免复制的一种方法。

void foo(const std::optional<std::reference_wrapper<const T>>& opt) {
if (opt) {
// Do something.
}
}
T t;
foo(t);

但考虑到C++委员会有充分的理由不允许在 std::optional 中引用。例如,"可选引用"本质上描述了纯指针的作用,而纯指针不受长类型名称的影响。

void foo(const T* opt) {
if (opt) {
// Do something.
}
}
T t;
foo(&t);

我想你会发现这个文档页面很有用。请参阅有关"可选函数参数"的部分。

当您调用函数并传递 T 的实例时,将构造一个可选函数,该可选函数将拥有自己的 T 副本,因此它将调用 T 的复制构造函数。

int main()
{
T t;
optional<T> ot;
foo(t);  // will create a copy
foo(ot); // won't create a copy
}

如果您使用的是boost::optional而不是std::optional,则可以将foo声明为接收可选引用,即

void foo(boost::optional<const T&> t)