www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Copy constructor in D. Why it is necessary to have it.

reply Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
http://www.everfall.com/paste/id.php?m46jrb36o7qu

This is a short example. It has all the comments inside. Since "in" keyword
tells the compiler to make a copy of an class object - a new object is created.
But constructor for this object is not called(you can check it). In my opinion
it is a big issue and needs to be improved.
Sep 30 2008
next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Tue, 30 Sep 2008 23:37:50 +0400, Eldar Insafutdinov  
<e.insafutdinov gmail.com> wrote:

 http://www.everfall.com/paste/id.php?m46jrb36o7qu

 This is a short example. It has all the comments inside. Since "in"  
 keyword tells the compiler to make a copy of an class object - a new  
 object is created.
No, that's not true. No heap activity is done under the hood, a copy of /pointer/ is passed (as opposed to a copy of /instance/). In means that changes to the variable won't be visible to the caller: void foo(in TreeIter it) { it = null; // makes local change } An important thing to note is that `in` is not recursive (as const or invariant).
 But constructor for this object is not called(you can check it). In my  
 opinion it is a big issue and needs to be improved.
No, it shouldn't generate heap activity unless really needed. In this case do the following: void foo(const(TreeIter) it) { auto itCopy = it.clone(); // do whatever you wish with a copy. } But in general, a const reference should be enough to you.
Sep 30 2008
prev sibling next sibling parent reply Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
Denis Koroskin Wrote:

 On Tue, 30 Sep 2008 23:37:50 +0400, Eldar Insafutdinov  
 <e.insafutdinov gmail.com> wrote:
 
 http://www.everfall.com/paste/id.php?m46jrb36o7qu

 This is a short example. It has all the comments inside. Since "in"  
 keyword tells the compiler to make a copy of an class object - a new  
 object is created.
No, that's not true. No heap activity is done under the hood, a copy of /pointer/ is passed (as opposed to a copy of /instance/). In means that changes to the variable won't be visible to the caller:
In my particular case changes are made to the data behind the pointer - and they are not copied because, only pointer itself is copied. In C++ when you call a function like this: foo(TClass instance); copy constructor is called to create a proper copy of an object. "in" keyword means exactly the same I guess? it makes a local copy of an object, so that variable is not supposed to be modified. But in my case since I use a binding to a C-library - the real data is behind the pointer. foo() cannot modify the class fields themself, but since pointer both in variable and local copy point to the same data - the semantics of "in" doesn't work.
     auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
Sep 30 2008
parent reply bearophile <bearophileHUGS lycos.com> writes:
Eldar Insafutdinov:
     auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
In D all objects are managed by reference. So when you copy automatically, you are just copying its reference, that's a pointer fully managed by the GC. If you want a copy of the data of an object you ask so to it. This simplifies collections and reduces the number of copies, improving performance. Instead of "clone()" I suggest "dup", that's the standard in D. Bye, bearophile
Sep 30 2008
next sibling parent BCS <ao pathlink.com> writes:
Reply to bearophile,

 Eldar Insafutdinov:
 
 auto itCopy = it.clone();
 
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
In D all objects are managed by reference.
BTW note that structs ARE pass by value.
Sep 30 2008
prev sibling parent "Bill Baxter" <wbaxter gmail.com> writes:
On Wed, Oct 1, 2008 at 5:34 AM, bearophile <bearophileHUGS lycos.com> wrote:
 Eldar Insafutdinov:
     auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
In D all objects are managed by reference. So when you copy automatically, you are just copying its reference, that's a pointer fully managed by the GC. If you want a copy of the data of an object you ask so to it. This simplifies collections and reduces the number of copies, improving performance. Instead of "clone()" I suggest "dup", that's the standard in D.
It has been pointed out though, that dup is a "shallow copy" in D's built-in usage. If you want a deep copy operation, there is no precedent in the base language, I believe. Clone is a good one to standardize on for deep copies, I think. --bb
Sep 30 2008
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Bill Baxter:
 It has been pointed out though, that dup is a "shallow copy" in D's
 built-in usage.  If you want a deep copy operation, there is no
 precedent in the base language, I believe.  Clone is a good one to
 standardize on for deep copies, I think.
I see. Probably the more readable & intuitive names are "copy" and "deepcopy". But "dup" is already present, so it has to be accepted, I presume. What about "deepdup" for the deep version instead? :-) It's more easy to remember its meaning (and I presume it's not that commonly used to deserve a very short name). Bye, bearophile
Sep 30 2008
parent reply "Bill Baxter" <wbaxter gmail.com> writes:
On Wed, Oct 1, 2008 at 5:55 AM, bearophile <bearophileHUGS lycos.com> wrote:
 Bill Baxter:
 It has been pointed out though, that dup is a "shallow copy" in D's
 built-in usage.  If you want a deep copy operation, there is no
 precedent in the base language, I believe.  Clone is a good one to
 standardize on for deep copies, I think.
I see. Probably the more readable & intuitive names are "copy" and "deepcopy". But "dup" is already present, so it has to be accepted, I presume. What about "deepdup" for the deep version instead? :-)
Heh, made me think .deeppoop when I first saw that.
 It's more easy to remember its meaning (and I presume it's not that commonly
used to deserve a very short name).
I like clone. It's used pretty commonly in other languages. I'd rather not follow up one slightly odd-ball name with an even more bizarre one. But it's not gonna be anything more than a convention anyway, so you're free to name it .deepdup if you like in your libraries. --bb
Sep 30 2008
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Bill Baxter:
 I like clone.  It's used pretty commonly in other languages.
Java?
 I'd rather not follow up one slightly odd-ball name with an even more
 bizarre one.  But it's not gonna be anything more than a convention
 anyway, so you're free to name it .deepdup if you like in your
 libraries.
If the D convention is clone I'll use clone! :-) Using different conventions is generally bad. Bye, bearophile
Sep 30 2008
parent "Bill Baxter" <wbaxter gmail.com> writes:
On Wed, Oct 1, 2008 at 6:53 AM, bearophile <bearophileHUGS lycos.com> wrote:
 Bill Baxter:
 I like clone.  It's used pretty commonly in other languages.
Java?
I've seen it used in C++ libs too.
 I'd rather not follow up one slightly odd-ball name with an even more
 bizarre one.  But it's not gonna be anything more than a convention
 anyway, so you're free to name it .deepdup if you like in your
 libraries.
If the D convention is clone I'll use clone! :-) Using different conventions is generally bad.
There is no real convention at this point. Has anyone seen a D library that contains a way to make deep copies of its objects? --bb
Sep 30 2008
prev sibling next sibling parent KennyTM~ <kennytm gmail.com> writes:
Bill Baxter wrote:
 On Wed, Oct 1, 2008 at 5:55 AM, bearophile <bearophileHUGS lycos.com> wrote:
 Bill Baxter:
 It has been pointed out though, that dup is a "shallow copy" in D's
 built-in usage.  If you want a deep copy operation, there is no
 precedent in the base language, I believe.  Clone is a good one to
 standardize on for deep copies, I think.
I see. Probably the more readable & intuitive names are "copy" and "deepcopy". But "dup" is already present, so it has to be accepted, I presume. What about "deepdup" for the deep version instead? :-)
Heh, made me think .deeppoop when I first saw that.
 It's more easy to remember its meaning (and I presume it's not that commonly
used to deserve a very short name).
I like clone. It's used pretty commonly in other languages. I'd rather not follow up one slightly odd-ball name with an even more bizarre one. But it's not gonna be anything more than a convention anyway, so you're free to name it .deepdup if you like in your libraries. --bb
I use .clone also, but the difference in meaning between .clone and .dup may not be clear enough to say the former is a deep copy but the latter is shallow. Ouch, but we have invariant vs const already, so maybe it's OK. /sarcasm
Oct 01 2008
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 But it's not gonna be anything more than a convention
 anyway, so you're free to name it .deepdup if you like in your
 libraries.
We've been informally calling it "deepdup". The advantage of that is it is fairly hard to misinterpret. Nobody liked my ".dupofearl" idea.
Oct 01 2008
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter Bright:
 We've been informally calling it "deepdup". The advantage of that is it 
 is fairly hard to misinterpret. Nobody liked my ".dupofearl" idea.
I agree that given the "dup", then then meaning of "deepdup" can be understood much better than "clone". On the other hand there are some name changes that can improve D2: 1) invariant => immutable 2) .length => .size 3) .dup => .copy 4) .deepdup => deepcopy 1 and 2) are surely improvements. 3) "dup" is used quite commonly, so it deserves a short name, but "copy" is just one character longer, it isn't an abbreviation, and it's more readable, so I think it's not bad. And 4) is just the natural extension of the name 3). It doesn't deserve a very short name because it's not used often, so it's better to make it as readable as possible. Bye, bearophile
Oct 01 2008
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"bearophile" wrote
 Walter Bright:
 We've been informally calling it "deepdup". The advantage of that is it
 is fairly hard to misinterpret. Nobody liked my ".dupofearl" idea.
I agree that given the "dup", then then meaning of "deepdup" can be understood much better than "clone". On the other hand there are some name changes that can improve D2: 1) invariant => immutable
Yes
 2) .length  =>  .size
No. Size can imply the memory size, so an array of ints, I might expect size to return 4*length.
 3) .dup  =>  .copy
either works for me.
 4) .deepdup  =>  deepcopy
either works for me.
 3) "dup" is used quite commonly, so it deserves a short name, but "copy" 
 is just one character longer, it isn't an abbreviation, and it's more 
 readable, so I think it's not bad.
character length is not as important as clarity, but dup seems pretty clear to me. If it were copy vs. duplicate, I'd go with copy for brevity, but either is fine. -Steve
Oct 01 2008
prev sibling next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
bearophile wrote:
 Walter Bright:
 We've been informally calling it "deepdup". The advantage of that is it 
 is fairly hard to misinterpret. Nobody liked my ".dupofearl" idea.
I agree that given the "dup", then then meaning of "deepdup" can be understood much better than "clone".
Everyone has a different opinion :-)
 On the other hand there are some name changes that can improve D2:
 1) invariant  =>  immutable
Seconded.
 2) .length  =>  .size
No. To me, 'size' should return the number of bytes of something, not the number of elements. 'length' is appropriate for what's being returned.
 3) .dup  =>  .copy
.dup is fine as is, and I think it should always perform a deep copy. With D going the direction it is, shallow copies are of limited use and can therefore be called .shallow or something.
 4) .deepdup  =>  deepcopy
Sean
Oct 01 2008
parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Wed, 01 Oct 2008 10:23:40 -0700,
Sean Kelly wrote:
 3) .dup  =>  .copy
.dup is fine as is, and I think it should always perform a deep copy. With D going the direction it is, shallow copies are of limited use and can therefore be called .shallow or something.
Deep copy is not possible without knowing the object structure. How about opDup? :)
Oct 02 2008
next sibling parent "Bill Baxter" <wbaxter gmail.com> writes:
On Fri, Oct 3, 2008 at 5:51 AM, Sergey Gromov <snake.scaly gmail.com> wrote:
 Wed, 01 Oct 2008 10:23:40 -0700,
 Sean Kelly wrote:
 3) .dup  =>  .copy
.dup is fine as is, and I think it should always perform a deep copy. With D going the direction it is, shallow copies are of limited use and can therefore be called .shallow or something.
Deep copy is not possible without knowing the object structure. How about opDup? :)
How would that differ from a function called dup? Anyway, copying objects is definitely another place D's story is a little weak. The class/struct distinction does relieve some of the pressure, but eventually you will run into situations where you want to copy an object. In my code I've been creating polymorphic copy(Type obj) functions that copy from obj to this. Then implementing dup in terms of copies like: Type dup() { ret = new Type; ret.copy(this); return ret; } The language could potentially help by automating some of that and calling an opCopy automatically when "dup" is invoked. But the above isn't terribly onerous. Just to be explicit about my understanding of the issues: The basic problem with just having a dup() is that if Deriv derives from Base and both implement dup, there's no way for Deriv's dup to use Base's dup. Both will try to allocate a whole object of their own type. So dup can't usefully be extended using virtual functions. A copy function can, though. void Deriv.copy(Deriv obj) { // copy from objs fields this.xxx = obj.xxx ; // copy super's fields super.copy(obj); } Copying and construction in C++ always seems to be good topics for tricky interview questions, so there's likely more involved than what I've just said. --bb
Oct 02 2008
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Sergey Gromov:
 Deep copy is not possible without knowing the object structure.  How 
 about opDup?  :)
An opCopy() / opDeepcopy looks useful (not opDup because in D special names are named about their meaning and not their syntax). In Python there are the standard special methods __copy__ and __deepcopy__ for that purpose (during deepcopying the system takes care of eventually present loops, this will be important in D too). Related to the copy, a opGetstate() / opSetstate() may be useful to serialize / deserialize objects on disk. In Python they of named __setstate__ / __getstate__, when they are present the pickle function uses them, otherwise it just reads/writes all the object attributes. Bye, bearophile
Oct 02 2008
prev sibling parent reply "Bent Rasmussen" <IncredibleShrinkingSphere Gmail.com> writes:
You have a procedural mind, Bearophile ;-)

"bearophile" <bearophileHUGS lycos.com> skrev i meddelelsen 
news:gbvmgr$19tu$1 digitalmars.com...
 Walter Bright:
 We've been informally calling it "deepdup". The advantage of that is it
 is fairly hard to misinterpret. Nobody liked my ".dupofearl" idea.
I agree that given the "dup", then then meaning of "deepdup" can be understood much better than "clone". On the other hand there are some name changes that can improve D2: 1) invariant => immutable 2) .length => .size 3) .dup => .copy 4) .deepdup => deepcopy 1 and 2) are surely improvements. 3) "dup" is used quite commonly, so it deserves a short name, but "copy" is just one character longer, it isn't an abbreviation, and it's more readable, so I think it's not bad. And 4) is just the natural extension of the name 3). It doesn't deserve a very short name because it's not used often, so it's better to make it as readable as possible. Bye, bearophile
Oct 01 2008
parent reply bearophile <bearophileHUGS lycos.com> writes:
Bent Rasmussen:
 You have a procedural mind, Bearophile ;-)
Is this a good or bad thing? :-) Bye, bearophile (lowercase)
Oct 01 2008
parent "Bent Rasmussen" <IncredibleShrinkingSphere Gmail.com> writes:
I'm talking out of my ass, as superdan would say, Bearophile*. Although your 
preferred names sound a "tad" more "procedural" to me. Ass-talking "off" :-)

- bent*

* It's a variable name!

"bearophile" <bearophileHUGS lycos.com> skrev i meddelelsen 
news:gc0pcp$1rqq$1 digitalmars.com...
 Bent Rasmussen:
 You have a procedural mind, Bearophile ;-)
Is this a good or bad thing? :-) Bye, bearophile (lowercase)
Oct 02 2008
prev sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Walter Bright wrote:
 Nobody liked my ".dupofearl" idea.
Why? :( Nothing can stop the .dupofearl ... -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Oct 01 2008
parent reply "Bill Baxter" <wbaxter gmail.com> writes:
On Thu, Oct 2, 2008 at 7:48 AM, Tom S <h3r3tic remove.mat.uni.torun.pl> wrote:
 Walter Bright wrote:
 Nobody liked my ".dupofearl" idea.
Why? :( Nothing can stop the .dupofearl ...
I think it's because it was too hard to tell if it was dup-of-earl or dup-o-fear---l. Beware! The Dup 'o Fear..l awaits you all with nasty big pointy teeth. --bb
Oct 01 2008
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 On Thu, Oct 2, 2008 at 7:48 AM, Tom S <h3r3tic remove.mat.uni.torun.pl> wrote:
 Walter Bright wrote:
 Nobody liked my ".dupofearl" idea.
Why? :( Nothing can stop the .dupofearl ...
I think it's because it was too hard to tell if it was dup-of-earl or dup-o-fear---l. Beware! The Dup 'o Fear..l awaits you all with nasty big pointy teeth. --bb
And when I dup you You will be my Duped, deep-duped of Earl We'll walk through my dupdom And the bits we will share
Oct 02 2008
parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Walter Bright wrote:
 Bill Baxter wrote:
 On Thu, Oct 2, 2008 at 7:48 AM, Tom S 
 <h3r3tic remove.mat.uni.torun.pl> wrote:
 Walter Bright wrote:
 Nobody liked my ".dupofearl" idea.
Why? :( Nothing can stop the .dupofearl ...
I think it's because it was too hard to tell if it was dup-of-earl or dup-o-fear---l. Beware! The Dup 'o Fear..l awaits you all with nasty big pointy teeth. --bb
And when I dup you You will be my Duped, deep-duped of Earl We'll walk through my dupdom And the bits we will share
Wow! You may not have a beard/mustache ( http://www.alenz.org/mirror/khason/why-microsoft-can-blow-off-with-c.html ), but D is destined to succeed simply because your nerdiness level beats everyone ;) Too bad you couldn't come to the Tango Conference... -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Oct 02 2008
prev sibling parent reply Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
bearophile Wrote:

 Eldar Insafutdinov:
     auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
In D all objects are managed by reference. So when you copy automatically, you are just copying its reference, that's a pointer fully managed by the GC. If you want a copy of the data of an object you ask so to it. This simplifies collections and reduces the number of copies, improving performance. Instead of "clone()" I suggest "dup", that's the standard in D. Bye, bearophile
Ah ok, so when using "in" with class objects - it means that I can't modify the reference itself. So no copy occured. I was wrong.
Sep 30 2008
parent "Bill Baxter" <wbaxter gmail.com> writes:
On Wed, Oct 1, 2008 at 6:01 AM, Eldar Insafutdinov
<e.insafutdinov gmail.com> wrote:
 bearophile Wrote:

 Eldar Insafutdinov:
     auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
In D all objects are managed by reference. So when you copy automatically, you are just copying its reference, that's a pointer fully managed by the GC. If you want a copy of the data of an object you ask so to it. This simplifies collections and reduces the number of copies, improving performance. Instead of "clone()" I suggest "dup", that's the standard in D. Bye, bearophile
Ah ok, so when using "in" with class objects - it means that I can't modify the reference itself. So no copy occured. I was wrong.
In D1 'in' is a no-op. It just means pass the parameter normally. Which for classes means you're actually passing a pointer/reference to the class. I've done very little with D2, but in D2 I think 'in' on a parameter means 'const'. Or maybe "const final". --bb
Sep 30 2008