why no copy constructor in java?

X

Xiaoshen Li

Dear All,

Sorry for coming back to the old topic. I really cannot understand what
some people has said before. Here I am not interested in clone(), sorry.

In C++, without copy constructor,

MyClass Obj_1 = new MyClass(args);
MyClass Obj_2 = Obj_1;

will make Obj_1 and Obj_2 share the same private object if MyClass has a
private variable which is class type. C++ textbooks say that this
behaviour(shallow copying) is usually un-acceptable. So we need to
provide our own copy constructor, to make sure Obj_1 and Obj_2 have the
identical, but separate private object(deep copying).

In JAVA,
MyClass Obj_1 = new MyClass(args);
MyClass Obj_2 = Obj_1;

will make Obj_1 and Obj_2 two names( two references ) for the same
object. JAVA is happy and accepts such behaviour. It seems to me it is
shallow copying in C++.

My questions is: why C++ cannot accept the shallow copying and JAVA can
and is happy to live with it?

Thank you very much.
 
D

Danno

Huh?
Your Obj_1 and Obj_2 are referencing the same object. There is no
copying involved whatsoever. Furthermore, your definition of shallow
vs. deep copy is far different from mine.. There are no copy
constructors in java, you can use the Prototype design pattern.
 
S

Stefan Schulz

In JAVA,
MyClass Obj_1 = new MyClass(args);
MyClass Obj_2 = Obj_1;

Which is actually much more like

MyClass *Obj_1 = new MyClass(args);
MyClass *Obj_2 = Obj_1;

Which involves no copying of the actual object living somewhere in the
heap at all.

Java is a funny beast. It has no pointers, except that everything that is
not a primitive is one. A java reference is actually a "polite pointer"
which disallows a lot of the unsafe operations (such as reinterpret_cast,
or pointer arithmetics).

HTH
Stefan
 
Z

zero

Xiaoshen Li said:
Dear All,

Sorry for coming back to the old topic. I really cannot understand
what some people has said before. Here I am not interested in clone(),
sorry.

In C++, without copy constructor,

MyClass Obj_1 = new MyClass(args);
MyClass Obj_2 = Obj_1;

will make Obj_1 and Obj_2 share the same private object if MyClass has
a private variable which is class type. C++ textbooks say that this
behaviour(shallow copying) is usually un-acceptable. So we need to
provide our own copy constructor, to make sure Obj_1 and Obj_2 have
the identical, but separate private object(deep copying).

In JAVA, MyClass Obj_1 = new MyClass(args);
MyClass Obj_2 = Obj_1;

will make Obj_1 and Obj_2 two names( two references ) for the same
object. JAVA is happy and accepts such behaviour. It seems to me it is
shallow copying in C++.

No, it is not shallow copying. It is in fact, like you said, two
references to *the same* object. Shallow copying in C++ means getting
two references to *two different* (but identical) objects.

The Java way is more like getting a C++ reference to the same object,
which is somewhat unusual, but not "usually unacceptable". Compare
this:

<java>
MyClass obj1 = new MyClass(args); // reference (pointer) to new object
MyClass obj2 = obj1; // reference to same object (no copying)
</java>

<C++>
MyClass obj1(args); // original object (not a pointer or reference!)
MyClass &obj2 = obj1; // reference to same object (no copying)
MyClass obj3 = obj1; // new but identical object (shallow copy)
</C++>

<C++>
MyClass *obj1(args); // pointer (reference) to new object
MyClass *obj2 = obj1; // pointer to the same object (no copying)
</C++>

As you can see, java is much more like the second C++ example, not the
first.
In C++ obj3 is created using the default copy constructor, and hence is a
shallow copy of obj1. In Java there is no default copy constructor - if
you want to copy an object you need to define your own copy constructor,
which could be a shallow or deep copy, depending on how you code it. The
more common way is to use clone though - but here too shallow or deep
copy depends on your own implementation.

<java>
MyClass obj3 = new MyClass(obj1); // copy constructor must be defined
MyClass obj4 = obj1.clone(); // clone must be defined
</java>

-- Beware the False Authority Syndrome
 
J

Jean-Francois Briere

By the way, in C++ it's more like:

MyClass Obj_1(args);
MyClass Obj_2 = Obj_1;

Regards
 
A

AndyRB

Xiaoshen said:
Dear All,

Sorry for coming back to the old topic. I really cannot understand what
some people has said before. Here I am not interested in clone(), sorry.

In C++, without copy constructor,

MyClass Obj_1 = new MyClass(args);
MyClass Obj_2 = Obj_1;

The above is incorrect it should either be:
MyClass * Obj_1 = new MyClass(args);
MyClass * Obj_2 = Obj_1;
Here only the pointer value is copied, both pointers will then point to
the same object.
or
MyClass Obj_1 = MyClass(args);
MyClass Obj_2 = Obj_1;
Here either the default memberwise shallow copy will be performed or
maybe a deep copy if the default copy constructor has been overridden.
will make Obj_1 and Obj_2 share the same private object if MyClass has a
private variable which is class type.
If MyClass has a pointer to allocated data and the class performs the
default memberwise shallow copy then Obj_1 and Obj_2 will both have
pointers pointing to the same data. This is the basic issue regarding
shallow copying of objects (where this sharing of a resource is not
desired or not intended).
C++ textbooks say that this
behaviour(shallow copying) is usually un-acceptable. So we need to
provide our own copy constructor, to make sure Obj_1 and Obj_2 have the
identical, but separate private object(deep copying).
In JAVA,
MyClass Obj_1 = new MyClass(args);
MyClass Obj_2 = Obj_1;

will make Obj_1 and Obj_2 two names( two references ) for the same
object. JAVA is happy and accepts such behaviour. It seems to me it is
shallow copying in C++.

In the above only the reference is copied and not the underlying
object, however, this doesn't necessarily create any issues as the
garbage collector is able to track when all references to the object
no-longer exist and know when the object's memory can be reclaimed. The
problem occurs when a copy results in more than one object sharing a
resource and both objects acting as though they are the sole owner of
that resource, i.e. they have not been designed to share the resource
or maybe the sharing was unintentional...
My questions is: why C++ cannot accept the shallow copying and JAVA can
and is happy to live with it?

The issue mainly crops up with value semantics (and particularly where
objects are passed-by-value) because the default copy-semantics only
performs a shallow copy, for example...
MyClass Foo()
{
MyClass Obj_1 = MyClass(args);
return Obj_1;
}
Imagine MyClass has a dynamic buffer and performs a shallow copy to the
object that will be returned from function foo. Obj_1 will then be
destroyed and, assuming the destructor does what it should and
deallocates the buffer, the pointer in the returned object will have
become invalidated since it was pointing to the dynamic buffer which
has now been deallocated.

If you change foo to use reference rather than value semantics, and
therefore behave more like you would expect in Java, the issue no
longer exists as no copying of the object will take place :-

std::auto_ptr<MyClass> Foo()
{
std::auto_ptr<MyClass> Obj_1 = new MyClass(args);
return Obj_1;
}
 
A

AndyRB

zero said:
No, it is not shallow copying. It is in fact, like you said, two
references to *the same* object. Shallow copying in C++ means getting
two references to *two different* (but identical) objects.
I don't think this is a good description of shallow copying as it can
also describe deep copying. In fact the issue of shallow copying is
that you end up with two references/pointers to *the same* object.
The Java way is more like getting a C++ reference to the same object,
which is somewhat unusual, but not "usually unacceptable". Compare
this:

<java>
MyClass obj1 = new MyClass(args); // reference (pointer) to new object
MyClass obj2 = obj1; // reference to same object (no copying)
</java>

<C++>
MyClass obj1(args); // original object (not a pointer or reference!)
MyClass &obj2 = obj1; // reference to same object (no copying)
MyClass obj3 = obj1; // new but identical object (shallow copy)
Or depending on the copy constructor.
MyClass obj3 = obj1; //new but identical object (deep copy)
 
Z

zero

I don't think this is a good description of shallow copying as it can
also describe deep copying. In fact the issue of shallow copying is
that you end up with two references/pointers to *the same* object.

I wasn't trying to define shallow copying. I merely wanted to explain
that after a shallow copy you have two references to different (yes
different, not the same, albeit identical) objects. If the object is a
compound object then the references inside both objects will be to the
same object/memory space. But the original object and its copy are not
the same.
Or depending on the copy constructor.
MyClass obj3 = obj1; //new but identical object (deep copy)

Only if you define your own copy constructor. The default copy
constructor is a shallow copy. This is fine for non-compound objects,
but not for compound objects. Hence the whole problem with shallow
copying: people not defining a copy constructor for compound objects.

This problem does not exist in Java because there is no default copy
constructor and clone is protected. If you want a copy of an object you
need to create a copy constructor or implement clone, both of which
protect you from forgetting to implement the copy constructor, as often
happens in C++. Of course it doesn't protect you from writing bad copy
code.
 
A

AndyRB

zero said:
I wasn't trying to define shallow copying. I merely wanted to explain
that after a shallow copy you have two references to different (yes
different, not the same, albeit identical) objects.
Yes this is true, but the same is also true for a deep copy.
If the object is a
compound object then the references inside both objects will be to the
same object/memory space.
Yes and it is this that is the important point that distinguishes a
shallow from a deep copy.
But the original object and its copy are not
the same.


Only if you define your own copy constructor. The default copy
constructor is a shallow copy. This is fine for non-compound objects,
but not for compound objects. Hence the whole problem with shallow
copying: people not defining a copy constructor for compound objects.

Sure, but in Java any object which contains another object is a
compound object. Most of time in c++ this is not the case and the
default copy constructor works fine, even where member objects will
need to perform a deep copy, example:
class SomeObj
{
std::vector<SomeCompoundObj> array_;
//Some other functions, but no user defined copy constructor.
}

SomeObj Obj1;
SomeObj Obj2(Obj1);
In the above the default copy constructor works fine because vector
performs a deep copy as does each SomeCompoundObj in the array.
This problem does not exist in Java because there is no default copy
constructor and clone is protected. If you want a copy of an object you
need to create a copy constructor or implement clone, both of which
protect you from forgetting to implement the copy constructor, as often
happens in C++.
Forgetting to implement the copy constructor sounds like a very poorly
designed class to me. If they forgot to implement the copy constructor
(or to disable it completely) it is most probably not the only thing
they forgot. Of course, both cloning and copy constructors in Java have
their own gotchas.
Of course it doesn't protect you from writing bad copy
code.
Sure, you can never protect a bad programmer from themselves.

Another important difference is that Java doesn't have implicit
copying, however, it is easier to correctly implement copying or
cloning in c++ than Java (IMHO).
 
Z

zero

Another important difference is that Java doesn't have implicit
copying, however, it is easier to correctly implement copying or
cloning in c++ than Java (IMHO).

Why do you think that? The only part of copying that I think is easier in
C++ than in Java is that in C++ the * syntax clearly shows when you're
working with pointers. The lack of a specific syntax in Java can make you
forget that every class-type variable is a reference - especially if you
come from C++.
 
A

AndyRB

zero said:
Why do you think that? The only part of copying that I think is easier in
C++ than in Java is that in C++ the * syntax clearly shows when you're
working with pointers. The lack of a specific syntax in Java can make you
forget that every class-type variable is a reference - especially if you
come from C++.

To be honest, thinking about it more, I am not sure there is much of a
difference.

But my original thoughts came from the fact that clone is often
criticised in Java, whereas in C++ once you have the copy constructor,
clone can then simply be implemented in terms of the copy constructor:-
virtual Dervied * Clone() { return new Derived(*this); }
And if you need to avoid any slicing issues, you just declare the copy
constructor as protected and therefore as an implementation mechanism
only.

Maybe a more significant factor is that the default copy (as in basic
memberwise copy not clone) is probably more often the appriopriate copy
to perform in C++ than in Java because every class-type variable is a
reference in Java, whereas often you have the class-value itself as the
data member in C++.
 
Joined
Aug 14, 2009
Messages
1
Reaction score
0
References(in java) and pointers are similar

Java references are nothing to do with c++ references.

Static allocation ==> allocation on stack segment
Dynamic allocation ==> allocation on heap segment

References in java are equivalent to pointers in c++

In java there is no static allocation of memory(Except primitive data types).
ex:01
Code:
c++==> Obj* o1;
is equivalent to
java ==> Obj o1;

In both cases memory is not allocated. Only references are present on stack segment.i.e. When we allocate memory they will point to some heap section memory.
Following ex:01
lets allocate memory
Code:
c++ ==> o1=new Obj();
java ==> o1=new Obj();

Are u seeing the similarity now.

Java has done this to have advantages of pointers without worrying about releasing it, In java Memory is released by a background thread which is called as Garbage collector. In c++ we have to take care of it.

If you know .net similar thing is there with classes. But they allowed allocating memory on stack segment for user defined objects via structurs i.e. struct. But any pointer operations must be in unsafe block of code. If you write such programs you can will have less security previlages than writing code that does not contain unsafe code. If you want to have security previlages then you have to generate native code i.e. code that is system dependent.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top