The Standard doesn't not require a compiler to perform return-value-optimization(RVO), but then, since C++11, the result must be moved.
It looks as if, this might introduce UB to/break code, which was valid in C++98.
For example:
#include <vector>
#include <iostream>
typedef std::vector<int> Vec;
struct Manager{
Vec& vec;
Manager(Vec& vec_): vec(vec_){}
~Manager(){
//vec[0]=42; for UB
vec.at(0)=42;
}
};
Vec create(){
Vec a(1,21);
Manager m(a);
return a;
}
int main(){
std::cout<<create().at(0)<<std::endl;
}
When compiled with gcc (or clang for that matter) with -O2 -fno-inline -fno-elide-constructors
(I'm using std::vector
with these build-option, in order to simplify the example. One could trigger the same behavior without these options with handmade-classes and a more complicated create
-function) everything is OK for C++98(-std=c++98
):
return a;
triggers copy-constructor, which leavesa
intact.- Destructor of
m
is called (must happens beforea
is destructed, becausem
is constructed aftera
). Accessinga
in destructor is unproblematic. - Destructor of
a
is called.
The result is as expected: 21
is printed (here live).
The situation is however different when built as C++11(-std=c++11
):
return a;
triggers move-constructor, which "destroys"a
.- Destructor of
m
is called, but now accessinga
is problematic, becausea
was moved and no longer intact. vec.at(0)
throws now.
Here is a live-demonstration.
Am I missing something and the example is problematic in C++98 as well?
Aucun commentaire:
Enregistrer un commentaire