У меня есть фрагмент общего кода, который при создании экземпляра сводится к:
struct A{...};
A f1(){
A ret;
std::pair<A&, int> p(ret, 1);
p = g(); // g returns a pair<A, int>, but I am not interested in g
return ret; // RVO :)
};
Насколько я понимаю, это будет работать с RVO.
вопрос в том, будет ли этот другой код возвращать объект типа A
с RVO?
A f2(){
std::pair<A, int> p;
p = g();
return p.first; // RVO ?
};
Я понимаю, что, поскольку возвращаемый объект скрыт, он не будет выполнять RVO или компилятор можетне сможет подобрать «оптимизацию».Но я не вижу фундаментальной причины, по которой это было бы невозможно, другими словами, я думаю, для последовательности, это должно сделать RVO (что я хочу).
Причина, по которой я спрашиваю, это потому, что ядумаю, f2
более элегантный код, чем f1
.
Должна ли эта последняя версия выполнять RVO?Если да, зависит ли это от компилятора?
Мой грубый тест с gcc 8.1 показывает, что RVO не работает в f2
и f3
ниже:
struct A{
double something;
A() = default;
A(A const& other) : something(other.something){std::cerr << "cc" << '\n';}
A(A&& other) : something(other.something){std::cerr << "mc" << '\n';}
};
A f1(){
A ret;
std::pair<A&, int> p(ret, 1);
p.first.something = 5.;
return ret; // RVO :)
};
A f2(){
std::pair<A, int> p;//(ret, 1);
p.first.something = 5.;
return p.first; // no RVO :(
};
A f3(){
std::pair<A, int> p;//(ret, 1);
p.first.something = 5.;
return std::move(p).first; // no RVO :(
};
int main(){
A a1 = f1(); // prints nothing, RVO
A a2 = f2(); // prints "cc"; no RVO! Why?
A a3 = f3(); // prints "mc" (no much gain in this case); still no RVO!
}