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:

  1. what going on? why value object "lose" string parameter? , where?
  2. it looks value returns have problems whereas other ones work fine. why people recommending nowadays return value , "the system takes care of rest"?
  3. what way return large objects?
  4. 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

Popular posts from this blog

Detect support for Shoutcast ICY MP3 without navigator.userAgent in Firefox? -

web - SVG not rendering properly in Firefox -

java - JavaFX 2 slider labelFormatter not being used -