You need to understand (N)RVO ((Named) Return Value Optimization) and Copy Elision.
Both are well described in the CPP standard here.
In most cases you do not need to fear expensiv copy operations. The compiler will use RVO to help you. However, there are corner cases, when RVO will not work. Again, please read about it.
You may imagine, that the compiler creates space for the return value outside of the function, so in the callers frame/scope. Then it is clear that no copying takes place.
In this respect it is better to create the return value first, and then return it. Then RVO can happen.
You may run into trouble with returning references to function local variables. This may create dangling references. (references to function local variables that go out of scope, after the function ends). If you want to use this, then you can use const
references.
So, you may use both of
#include <utility>
#include <string>
#include <vector>
using namespace std::string_literals;
std::pair<bool, std::vector<int>> get1(const std::string &id) {
std::pair<bool, std::vector<int>> result{true, {}};
return result;
}
struct st{};
std::pair<bool, st> get2(const std::string& id) {
std::pair<bool, st> result{true, {}};
return result;
}
int main() {
const auto& [a1, b1] = get1("1"s);
auto [a2, b2] = get1("1"s);
const auto& [c1, d1] = get2("1"s);
auto [c2, d2] = get2("1"s);
return a1 and a2 and c1 and c2;
}
The recommendation is to go with the const
version, if possible.
Look at the output on Compiler Explorer
And see what Clang does :-)