Reputation: 1203
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?
Upvotes: 8
Views: 11184
Reputation: 4105
I think you will find useful this documentation page. See the section about "Optional function parameters".
When you call the function and pass an instance of T, an optional will be constructed which will own its own copy of T, therefore it will call T's copy constructor.
int main()
{
T t;
optional<T> ot;
foo(t); // will create a copy
foo(ot); // won't create a copy
}
If you're using boost::optional
, not std::optional
, you can declare foo as receiving an optional reference, i.e.
void foo(boost::optional<const T&> t)
Upvotes: 4
Reputation: 3791
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);
Upvotes: 8
Reputation: 4153
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.
Upvotes: 4