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 leavesaintact.- Destructor of
mis called (must happens beforeais destructed, becausemis constructed aftera). Accessingain destructor is unproblematic. - Destructor of
ais 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
mis called, but now accessingais problematic, becauseawas 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