7

I know that std::optional<T&> isn't supported in the standard. This question is about whether passing std::optional<T>& has any performance advantage

Sample code (https://godbolt.org/z/h56Pj6d6z) reproduced here

#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);
}

(My actual use case is an optional for a complex user-defined type, but I hope that a long string would do the same compiler-wise)

In this case, does DoStuffRef actually save any copying effort compared to DoStuff?

I tried to look at godbolt output but I don't know enough assembly to be sure. I do see that in the case of DoStuff, there seems to be a temp std::optional<T> created which is not present in DoStuffRef so my suspicion is that yes, passing an optional by reference save some copying

Appreciate the help!

resnet
  • 398
  • 3
  • 12

2 Answers2

5

If you pass actual std::optional<std::string> then yes, there would be no copy. But if you pass just std::string then temporary optional has to be constructed first, resulting in a copy of the string.

yuri kilochek
  • 12,709
  • 2
  • 32
  • 59
  • so in this case when I assign `str` to a string value and pass it on, since `str` is still of type `std::optional`, I should save a copy by using `DoStuffRef` right? – resnet Sep 22 '21 at 03:09
  • 1
    I think in C++17 it won't create a copy because "(8)" in https://en.cppreference.com/w/cpp/utility/optional/optional – alfC Sep 22 '21 at 03:09
  • @resnet exactly. – yuri kilochek Sep 22 '21 at 12:02
  • @alfC sure, if the `std::string` is rvalue, it will be a move instead if a copy, but the temporary will still be constructed. – yuri kilochek Sep 22 '21 at 12:04
4

DoStuffRef saves an extra copy when argument is already std::optional<std::string> (as in your example).

But, if you pass directly a std::string, then if both cases, a std::optional should be constructed, involving copy/move constructor of the string.

Jarod42
  • 203,559
  • 14
  • 181
  • 302