views:

300

answers:

9

Can someone give an example of a situation where a shallow copy is needed?

Note that in some situations, shallow copy and deep copy are the same. This can happen when the object has no ownership over any of its subvariables; that is, all subvariables are aggregated. I'd like to see examples where the an object is composed from variables which it owns, and it still is desirable to copy them shallowly.

Remark: I don't care in which language the examples are given. I'm asking this question from a C++/Java/C# point of view, although I think copying is a language agnostic concept.

+3  A: 

One possible use case is when the composed objects can be derived from state information that is present in the shallow copy and you want, for instance, to serialize your object.

You can store the shallow copy and then rebuild the complete object from the state upon deserialization.

Vinko Vrsalovic
That's a great example! Thanks.
Dimitri C.
By the way, have you ever encountered a situation where it was impossible or undesirable to copy the not-owned data, and thus serializing a dangling pointer?
Dimitri C.
External resources (database connections, for example) are 'non copyable'. But that doesn't mean you have to store a dangling pointer, you can prepare for it by releasing the resource before serializing.
Vinko Vrsalovic
With "dangling pointer" I meant a kind of dangling serialized reference.
Dimitri C.
+1  A: 

As I pointed out in my answer to your related question, many languages don't really have the concept of shallow and deep copy. However, this class in C++, which prevents you from using a NULL pointer may be an example where a "shallow" copy is needed:

template <typename T>
struct NotNull {

   T * p;

   NotNull( T * t ) : p( t ) {}

   T & operator *() { 
       if ( ! p ) {
          throw "null!";
       }
       return * p;
   }
};

The class does not own the thing pointed to, so no copy should be made.

anon
+3  A: 

Coming from C++ POV, there would be one scenario that i will use shallow copy : when implementing copy-on-write mechanism.

YeenFei
Yep, lazy copying is another good example, thanks! Although conceptually, it still is a deep copy, of course :p
Dimitri C.
+5  A: 

When the owned variables are immutable types, a shallow copy is sufficient. A deep copy is possible, but would only result in additional memory use.

Niels van der Rest
Indeed! Although this is a special case of lazy copying, so I make the same remark as to YeenFei: conceptually, it still is a deep copy.
Dimitri C.
+1  A: 

My take on this is that the situations where you would use deep copy are different for C++ versus Java.

  • In C++, you might use deep copying to avoid difficult memory management issues, or to make it easier to implement a multi-threaded application.

  • In Java, deep copying is not necessary for those reasons. Since the languages are both garbage collected, it is not necessary to go through hoops to free data structures. So a deep copy is not necessary to simplify the problem. Similarly Java has built-in support for synchronizing access by multiple threads to shared data structures.

In most cases, deep copying is unnecessary in Java assuming that your application's data structures are well designed.

Stephen C
+1  A: 
class Element{
}

class Example {
    private List<Element> elementList = new ArrayList<Element();

    public List<Element> getElementList() {
        return new ArrayList<Element>(this.elementList);
    }

    public void addElement(Element e) {
        elementList.add(e);
    }

    public void removeElement(Element e) {
        elementList.remove(e);
    }
}

You want all modifications of Example.elementList to be done by object methods, but you want to expose elements stored in list. So you create getter which returns a shallow copy. Copy, because you don't want caller to modify object's list and shallow because you want to expose objects from list, not their copies.

Tadeusz Kopec
+2  A: 

If you look at the Gang of Four design patterns, there's a pattern called FlyWeight. Here's a quote from wikipedia:

A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory.

This would be an acceptable use of a shallow copy.

Miguel Ping
+1  A: 

Shallow copies are quicker to make, which is often desirable for obvious reasons. The ultimate in shallow copying is obviously just a copy of a reference to the original object. If you're not mutating an object and can guarantee it won't get changed in other ways while you work with it then the more shallow the copy is, the better.

Kylotan
A: 

Remark: I don't care in which language the examples are given. I'm asking this question from a C++/Java/C# point of view, although I think copying is a language agnostic concept.

I think it depends quite a bit on the language.

In C++, copying plays a very different role than it does in Java/C#. In C++, I can't think of many cases where shallow copying makes sense. You'd usually just create references or pointers to an object instead. Copy constructors usually implement deep copies because in C++, an object takes ownership of its members, and is responsible for managing their lifetime. Because there's no GC, these ownership semantics become important, and you can't just have two objects pointing to a third without special care (do they use reference counting to keep the third alive? If not, which of the two objects owns it?)

I'd even say that the distinction between "deep" and "shallow" copies doesn't really make sense in C++. A copy creates all that is necessary for the newly created object to work. Sometimes, it shares a bit of data (typically data which isn't owned by either object), so it might not be a "true" deep copy", but it's not shallow either, because the bulk of the class typically is copied.

jalf
Interesting remark. You're quite right that C++ heavily relies on deep copying and that ownership is more important than in C# or Java. However, deep copying is relevant in C# and Java also, although it is needed much less often. I think that indeed in C# or Java one is more tempted to implement a shallow copy, but I suspect that is because implementing a deep copy is more bothersome, and in most cases the shallow copy will be accidentally sufficient.
Dimitri C.