Does an std::optional parameter create a copy?

Viewed 5659

I have a function that takes an std::optional

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

But copying T is expencive.

Does this create a copy of T?

If so, how can I not create a copy?

3 Answers

As clarified by your follow up comment, you are calling the function foo like this:

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

In this case, the answer is yes. A copy of t will be created. To avoid that, you can use std::reference_wrapper to avoid copying:

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

With these changes to the function, calling the it in the same manner will not result in creation of a copy.

Yes, std::optional stores a copy of whatever you pass to it. The C++17 standard explicitly prohibits storing references in std::optional. See: https://en.cppreference.com/w/cpp/utility/optional#:~:text=There%20are%20no%20optional%20references

As suggested by others, passing std::optional<std::reference_wrapper<const T>> is one way to avoid making copies.

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

T t;
foo(t);

But consider that the C++ committee had good reasons for disallowing references in std::optional. For instance, an "optional reference" essentially describes what a plain pointer does, and plain pointers don't suffer from the long type name.

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

T t;
foo(&t);
Related