Note that there are some explanatory texts on larger screens.

plurals
  1. POCopying big objects, c++
    primarykey
    data
    text
    <p>I am sure this has been answered, but I am no programmer and couldn't find/understand the appropriate answer. Suppose I have a massive class <code>big</code> for which would like to overload a binary operator, say <code>operator +</code>. </p> <ol> <li>Is there a sane way to make <code>big X=Y+Z</code> to build the sum directly into <code>X</code>, instead of creating temporary object, copying it to <code>X</code> and then destroying the temporary?</li> <li>The only thing that come into my mind is to wrap <code>big</code> into another class <code>small</code> that will contain the pointer to <code>big</code> and add <code>int use;</code> number of references to to big, so that <code>big</code> object get destroyed when <code>use==0</code>. And add another assignment operator, say <code>&lt;=</code> for actual copying. I tried to implement it (below). It seems to work, but I have no experience and it is hard for me to foresee, what can go wrong. Shouldn't be there a simpler solution?</li> </ol> <p>Code:</p> <pre><code>#include &lt;iostream&gt; // print and execute cmd #define Do(cmd) cout &lt;&lt; "\n\n\t"&lt;&lt; ++line &lt;&lt; ".\t" &lt;&lt; #cmd &lt;&lt; ";\n" &lt;&lt; endl; cmd; // print small object: name(small.id[big.id,u=big.use,x=big.x]) #define Show(avar) cout &lt;&lt; #avar &lt;&lt; "(" &lt;&lt; (avar).id &lt;&lt; "[" &lt;&lt; ((avar).data==NULL?0:(avar).data-&gt;id) &lt;&lt; ",u=" &lt;&lt; ((avar).data==NULL?0:(avar).data-&gt;use) &lt;&lt; ",x=" &lt;&lt; ((avar).data==NULL?0:(avar).data-&gt;x) &lt;&lt; "])" using namespace std; class big{ public: static int N; // biggest id in use int id; // unique id for each object int use; // nuber of references to this object int x; // data big() __attribute__((noinline)) { id=++N; use=1; x=0; cout &lt;&lt; "big.constructor.def: [" &lt;&lt; id &lt;&lt; ",u=" &lt;&lt; use &lt;&lt; ",x="&lt;&lt;x&lt;&lt;"]" &lt;&lt; endl; } big(const int&amp; y) __attribute__((noinline)) { id=++N; x=y; use=1; cout &lt;&lt; "big.constructor.int: [" &lt;&lt; id &lt;&lt; ",u=" &lt;&lt; use &lt;&lt; ",x="&lt;&lt;x&lt;&lt;"]" &lt;&lt; endl; } big(const big&amp; b) __attribute__((noinline)) { id=++N; use=1; x=b.x; cout &lt;&lt; "big.constructor.copy: [" &lt;&lt; id &lt;&lt; ",u=" &lt;&lt; use &lt;&lt; ",x="&lt;&lt;x&lt;&lt;"]" &lt;&lt; endl; } ~big() __attribute__((noinline)) { if(use&gt;0) throw 99; // destroing referenced data! cout &lt;&lt; "big.destructor: [" &lt;&lt; id &lt;&lt; ",u=" &lt;&lt; use &lt;&lt; ",x="&lt;&lt;x&lt;&lt;"]" &lt;&lt; endl; } friend class small; }; class small{ public: static int N; // biggest id in use int id; // unique id big * data; // reference to the actual data small() __attribute__((noinline)) { id=++N; data=NULL; // contains no data cout &lt;&lt; "small.constructor.def: "; Show(*this)&lt;&lt; endl; } small(const int&amp; y) __attribute__((noinline)) { id=++N; data=new big (y); // relies on the big constructor cout &lt;&lt; "small.constructor.int: "; Show(*this)&lt;&lt;endl; } small(const small&amp; y) __attribute__((noinline)) { id=++N; data=y.data; // new object refers to the same data!! if(data!=NULL) ++(data-&gt;use); // new reference added; cout &lt;&lt; "small.constructor.copy: "; Show(y) &lt;&lt; "--&gt;"; Show(*this) &lt;&lt; endl; } ~small(){ cout &lt;&lt; "small.destructor: "; Show(*this)&lt;&lt; endl; if(data!=NULL){ // is there data? --(data-&gt;use); // one reference is destroyed if(data-&gt;use == 0) // no references left, kill the data delete data; } } const small&amp; operator= (const small&amp; b) __attribute__((noinline)) { cout &lt;&lt; "equal: "; Show(*this) &lt;&lt; " = "; Show(b)&lt;&lt;endl; if(data != NULL){ // is there data in the target? --(data-&gt;use); // one reference is destroyed if(data-&gt;use == 0) // no references left, delete data; // kill the data } data=b.data; // target referenses the same data as the source! if(data!=NULL) ++(data-&gt;use); // new references added cout &lt;&lt; "Done equal: "&lt;&lt;endl; return *this; } // &lt;= will be used for actual copying the data const small&amp; operator&lt;= (const small&amp; b) __attribute__((noinline)) { cout &lt;&lt; "Copy: "; Show(*this) &lt;&lt; " &lt;= "; Show(b)&lt;&lt;endl; if(data != NULL){ // is there data in the target? --(data-&gt;use); // one reference is destroyed if(data-&gt;use == 0) // no references left, delete data; // kill the data } if(b.data==NULL) // source has no data data=NULL; else data = new big(*(b.data)); // make new copy of the data // via big's copy constructor cout &lt;&lt; "Done copy: "&lt;&lt;endl; return *this; } small operator+ (const small&amp; b) __attribute__((noinline)) { cout &lt;&lt; "Plus: "; Show(*this) &lt;&lt; " + "; Show(b)&lt;&lt; endl; if(this-&gt;data == NULL | b.data == NULL) throw 99; // missing data for + small ret(data-&gt;x); ret.data-&gt;x += b.data-&gt;x; cout &lt;&lt; "Return: "; Show(ret)&lt;&lt;endl; return ret; } }; int big::N=0; int small::N=0; main(){ int line=0; Do(small X(5); small Y(6); small Z(7); small W(X)); Show(X) &lt;&lt; endl; Show(Y) &lt;&lt; endl; Show(Z) &lt;&lt; endl; Show(W) &lt;&lt; endl; Do(X=Y; Z&lt;=Y); Show(X)&lt;&lt;endl; Show(Y)&lt;&lt;endl; // X and Y refer to the same data Show(Z)&lt;&lt;endl; // Z has a copy of data in Y Do(X=Z; Y=Z); Show(X)&lt;&lt;endl; Show(Y)&lt;&lt;endl; Show(Z)&lt;&lt;endl; // data previosly in X,Y destroyed Do(small* U=new small (17); small* T=new small (*U)); Show(*U) &lt;&lt; endl; Show(*T) &lt;&lt; endl; // U and T refer to the same big Do(delete U); Show(*T) &lt;&lt; endl; // big stays since there is another reference to it Do(delete T); // big destroyed Do(X=(Y+Z)+W); Show(X)&lt;&lt;endl; Show(Y)&lt;&lt;endl; Show(Z)&lt;&lt;endl; // no extra copying of data occures cout &lt;&lt; "\n\tEND\n" &lt;&lt; endl; } </code></pre> <p>Output:</p> <pre><code>1. small X(5); small Y(6); small Z(7); small W(X); big.constructor.int: [1,u=1,x=5] small.constructor.int: *this(1[1,u=1,x=5]) big.constructor.int: [2,u=1,x=6] small.constructor.int: *this(2[2,u=1,x=6]) big.constructor.int: [3,u=1,x=7] small.constructor.int: *this(3[3,u=1,x=7]) small.constructor.copy: y(1[1,u=2,x=5])--&gt;*this(4[1,u=2,x=5]) X(1[1,u=2,x=5]) Y(2[2,u=1,x=6]) Z(3[3,u=1,x=7]) W(4[1,u=2,x=5]) 2. X=Y; Z&lt;=Y; equal: *this(1[1,u=2,x=5]) = b(2[2,u=1,x=6]) Done equal: Copy: *this(3[3,u=1,x=7]) &lt;= b(2[2,u=2,x=6]) big.destructor: [3,u=0,x=7] big.constructor.copy: [4,u=1,x=6] Done copy: X(1[2,u=2,x=6]) Y(2[2,u=2,x=6]) Z(3[4,u=1,x=6]) 3. X=Z; Y=Z; equal: *this(1[2,u=2,x=6]) = b(3[4,u=1,x=6]) Done equal: equal: *this(2[2,u=1,x=6]) = b(3[4,u=2,x=6]) big.destructor: [2,u=0,x=6] Done equal: X(1[4,u=3,x=6]) Y(2[4,u=3,x=6]) Z(3[4,u=3,x=6]) 4. small* U=new small (17); small* T=new small (*U); big.constructor.int: [5,u=1,x=17] small.constructor.int: *this(5[5,u=1,x=17]) small.constructor.copy: y(5[5,u=2,x=17])--&gt;*this(6[5,u=2,x=17]) *U(5[5,u=2,x=17]) *T(6[5,u=2,x=17]) 5. delete U; small.destructor: *this(5[5,u=2,x=17]) *T(6[5,u=1,x=17]) 6. delete T; small.destructor: *this(6[5,u=1,x=17]) big.destructor: [5,u=0,x=17] 7. X=(Y+Z)+W; Plus: *this(2[4,u=3,x=6]) + b(3[4,u=3,x=6]) big.constructor.int: [6,u=1,x=6] small.constructor.int: *this(7[6,u=1,x=6]) Return: ret(7[6,u=1,x=12]) Plus: *this(7[6,u=1,x=12]) + b(4[1,u=1,x=5]) big.constructor.int: [7,u=1,x=12] small.constructor.int: *this(8[7,u=1,x=12]) Return: ret(8[7,u=1,x=17]) equal: *this(1[4,u=3,x=6]) = b(8[7,u=1,x=17]) Done equal: small.destructor: *this(8[7,u=2,x=17]) small.destructor: *this(7[6,u=1,x=12]) big.destructor: [6,u=0,x=12] X(1[7,u=1,x=17]) Y(2[4,u=2,x=6]) Z(3[4,u=2,x=6]) END small.destructor: *this(4[1,u=1,x=5]) big.destructor: [1,u=0,x=5] small.destructor: *this(3[4,u=2,x=6]) small.destructor: *this(2[4,u=1,x=6]) big.destructor: [4,u=0,x=6] small.destructor: *this(1[7,u=1,x=17]) big.destructor: [7,u=0,x=17] </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload