c++ - Strange behavior of copy-/move-constructors & how to return large objects? -
i have been experimenting c++11 again recently, after absence, , after reading many articles on internet thoroughly confused efficient way return large objects factory functions (basically, data analysis database).
i have become fan of unique_ptr, read in several articles because of new move-constructors possible return big vector by value , because of these new semantics should fast copying 1 pointer.
to try out, wrote small test program outputs in various constructors:
#include <iostream> #include <memory> using namespace std; class c { public: c( string n ) : _name{n} { cout << "constructing c named '" << _name << "'\n"; }; c() : _name( "empty" ) { cout << "default-constructing c named '" << _name << "'\n"; } ; // default-ctor c( const c& c ) : _name{c._name} { _name += " [copied]"; cout << "copy-constructing c named '" << _name << "'\n"; }; c( c&& c ) : _name{c._name} { _name += " [moved]"; cout << "move-constructing c named '" << _name << "'\n"; }; ~c() { cout << "destructing c named '" << _name << "'\n"; }; string getname() { return _name; }; private: string _name; };
and tested with
c fooval() { cout << "in fooval\n"; string str = "value return"; c c(str); return c; } c& fooref() { cout << "in fooref\n"; string str = "reference return"; c* pc = new c( str ); return *pc; } c* fooptr() { cout << "in fooptr\n"; string str = "classical pointer return"; c* pc = new c( str ); return pc; } unique_ptr<c> foouptr() { cout << "in foouptr\n"; string str = "unique_ptr return"; return unique_ptr<c>(new c(str)); } shared_ptr<c> foosptr() { cout << "in foosptr\n"; string str = "shared_ptr return"; return shared_ptr<c>(new c(str)); } // important: needs compiled flag -fno-elide-constructors int main(int argc, const char * argv[]) { c cv(fooval()); cout << "cv constructed\n"; c& cr = fooref(); cout << "cr constructed\n"; c* pc = fooptr(); cout << "*pc constructed\n"; unique_ptr<c> upc = foouptr(); cout << "*upc constructed\n"; shared_ptr<c> spc = foosptr(); cout << "*spc constructed\n"; cout << "alive: " << cv.getname() << ", " << cr.getname() << ", " << pc->getname() << ", " << upc->getname() << ".\n"; }
now, if compile as-is, compiler optimizes away ("elides") various constructor calls , output:
in fooval constructing c named 'value return' cv constructed in fooref constructing c named 'reference return' cr constructed in fooptr constructing c named 'classical pointer return' *pc constructed in foouptr constructing c named 'unique_ptr return' *upc constructed in foosptr constructing c named 'shared_ptr return' *spc constructed alive: value return, reference return, classical pointer return, unique_ptr return. destructing c named 'shared_ptr return' destructing c named 'unique_ptr return' destructing c named 'value return'
ok, can see how copying has been optimized away. see "specified" behaviour, compiled flag -fno-elide-constructors (i'm using apple llvm version 4.2 (clang-425.0.28)). following output:
in fooval constructing c named 'value return' destructing c named 'value return' move-constructing c named ' [moved]' destructing c named '' cv constructed in fooref constructing c named 'reference return' cr constructed in fooptr constructing c named 'classical pointer return' *pc constructed in foouptr constructing c named 'unique_ptr return' *upc constructed in foosptr constructing c named 'shared_ptr return' *spc constructed alive: [moved], reference return, classical pointer return, unique_ptr return. destructing c named 'shared_ptr return' destructing c named 'unique_ptr return' destructing c named ' [moved]'
so, clearly, fishy going on value-returned object. obviously, more small problem, because have expected -fno-elide-constructors not change semantics, amount of constructors involved.
thus ask:
- what going on? why value object "lose" string parameter? , where?
- it looks value returns have problems whereas other ones work fine. why people recommending nowadays return value , "the system takes care of rest"?
- what way return large objects?
- am making mistake somewhere not seeing?
thanks!
it looks it's clang bug: http://llvm.org/bugs/show_bug.cgi?id=12208 while simplified string concatenation related , apparently still not fixed.
Comments
Post a Comment