why no copy constructor in java?

Discussion in 'Java' started by Xiaoshen Li, Dec 22, 2005.

  1. Xiaoshen Li

    Xiaoshen Li Guest

    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.
     
    Xiaoshen Li, Dec 22, 2005
    #1
    1. Advertising

  2. Xiaoshen Li

    Danno Guest

    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.
     
    Danno, Dec 22, 2005
    #2
    1. Advertising

  3. On Thu, 22 Dec 2005 11:49:47 +0000, Xiaoshen Li wrote:


    > 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

    --
    You can't run away forever,
    But there's nothing wrong with getting a good head start.
    --- Jim Steinman, "Rock and Roll Dreams Come Through"
     
    Stefan Schulz, Dec 22, 2005
    #3
  4. Xiaoshen Li

    zero Guest

    Xiaoshen Li <> wrote in news:doegn6$36s9$:

    > 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
     
    zero, Dec 22, 2005
    #4
  5. By the way, in C++ it's more like:

    MyClass Obj_1(args);
    MyClass Obj_2 = Obj_1;

    Regards
     
    Jean-Francois Briere, Dec 22, 2005
    #5
  6. Xiaoshen Li

    AndyRB Guest

    Xiaoshen Li wrote:
    > 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;
    }
    >
    > Thank you very much.
     
    AndyRB, Dec 23, 2005
    #6
  7. Xiaoshen Li

    AndyRB Guest

    zero wrote:
    > Xiaoshen Li <> wrote in news:doegn6$36s9$:
    >
    > > 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.

    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)

    > </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
     
    AndyRB, Dec 23, 2005
    #7
  8. Xiaoshen Li

    zero Guest

    "AndyRB" <> wrote in
    news::

    > zero wrote:
    >>
    >> 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.


    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.

    >>
    >> <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)


    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.

    --
    Beware the False Authority Syndrome
     
    zero, Dec 23, 2005
    #8
  9. Xiaoshen Li

    AndyRB Guest

    zero wrote:
    > "AndyRB" <> wrote in
    > news::
    >
    > > zero wrote:
    > >>
    > >> 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.

    >
    > 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.
    >
    > >>
    > >> <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)

    >
    > 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).

    >
    > --
    > Beware the False Authority Syndrome
     
    AndyRB, Dec 23, 2005
    #9
  10. Xiaoshen Li

    zero Guest

    "AndyRB" <> wrote in news:1135342995.115424.168520
    @g44g2000cwa.googlegroups.com:

    > 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++.

    --
    Beware the False Authority Syndrome
     
    zero, Dec 23, 2005
    #10
  11. Xiaoshen Li

    AndyRB Guest

    zero wrote:
    > "AndyRB" <> wrote in news:1135342995.115424.168520
    > @g44g2000cwa.googlegroups.com:
    >
    > > 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++.


    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++.
    >
    > --
    > Beware the False Authority Syndrome
     
    AndyRB, Dec 23, 2005
    #11
  12. Xiaoshen Li

    spsarolkar

    Joined:
    Aug 14, 2009
    Messages:
    1
    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.
     
    spsarolkar, Aug 14, 2009
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Aire
    Replies:
    3
    Views:
    470
    Mike Wahler
    Jan 25, 2004
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,003
    Smokey Grindel
    Dec 2, 2006
  3. rdc02271
    Replies:
    24
    Views:
    743
    Jacek Dziedzic
    Dec 27, 2005
  4. Generic Usenet Account
    Replies:
    10
    Views:
    2,248
  5. cinsk
    Replies:
    35
    Views:
    2,615
    James Kanze
    Oct 11, 2010
Loading...

Share This Page