In a return statement, when the operand is the name of a non-volatile object with automatic storage duration, which isn't a function parameter or a catch clause parameter, and which is of the same class type (ignoring cv-qualification) as the function return type. This variant of copy elision is known as NRVO, "named return value optimization."
#include <iostream>
#include <optional>
#include <string>
// optional can be used as the return type of a factory that may fail
std::optional<std::string> create(bool b)
{
if (b)
return "Godzilla";
return {};
}
// std::nullopt can be used to create any (empty) std::optional
auto create2(bool b)
{
return b ? std::optional<std::string>{"Godzilla"} : std::nullopt;
}
int main()
{
std::cout << "create(false) returned "
<< create(false).value_or("empty") << '\n';
// optional-returning factory functions are usable as conditions of while and if
if (auto str = create2(true))
std::cout << "create2(true) returned " << *str << '\n';
}
optional<A> introduce_option_0(int n) {
A temp(someFn(n));
return temp;
}
很明显这会破坏NRVO的条件,但究竟相差多少呢?有没有挽回办法?
我找了网上目前常见的写法,我们可能有以下变体
optional<A> introduce_option_0(int n) {
A temp(someFn(n));
return temp;
}
optional<A> introduce_option_1(int n) {
A temp(someFn(n));
return std::move(temp);
}
optional<A> introduce_option_2(int n) {
A temp(someFn(n));
return {temp};
}
optional<A> introduce_option_3(int n) {
A temp(someFn(n));
return {std::move(temp)};
}
为了探究NRVO的条件和优化程度,对原本的函数也使用这4种变体
A always_success_0(int n) {
A temp(someFn(n));
return temp;
}
A always_success_1(int n) {
A temp(someFn(n));
return std::move(temp);
}
A always_success_2(int n) {
A temp(someFn(n));
return {temp};
}
A always_success_3(int n) {
A temp(someFn(n));
return {std::move(temp)};
}