Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Deep copying

51 views
Skip to first unread message

Paul

unread,
Aug 19, 2015, 3:34:33 AM8/19/15
to
A question asked in a job interview on deep copying is available here: http://www.careercup.com/question?id=6304195600711680

I will repeat it here:
BEGIN QUOTE
Write a function called deepCopy that takes an object and creates a deep copy of it.
var newObj = deepCopy(obj);
(can't use JSON, can't use prototype)
END QUOTE

I realise that this was not intended as a c++ question, but I can't see a way to do this in c++ because of the huge generality of the question, even though I have a basic understanding of deep copying. Can anyone help me get an answer in c++ (or help me understand the answers that are already provided.)?

Below is the URL that I use to understand deep copying. If you feel that there is anything wrong or incomplete about it, please comment so that I am not misled. I understand that this is intended to cover earlier versions of c++. I'm just trying to understand the basics, rather than worrying about c++ 11 improvements. Clearly, it's not intended to be c++ 11. For example, 0 is used in place of nullptr.

http://www.learncpp.com/cpp-tutorial/912-shallow-vs-deep-copying/

Thank you very much for your help,

Paul

Juha Nieminen

unread,
Aug 19, 2015, 4:19:32 AM8/19/15
to
Paul <peps...@gmail.com> wrote:
> I realise that this was not intended as a c++ question, but I can't see
> a way to do this in c++ because of the huge generality of the question

Well, objects themselves are "deep-copied" by simply using their copy
constructor or copy assignment. OTOH, if the object in question is
managing some allocated data, then it depends on the class's specification.

In general, in a well-designed C++ program, it's up to the class itself
(rather than the calling code) whether it internally uses deep or shallow
copying of any data it has allocated (or possibly something else, like
copy-on-write).

Of course nothing stops a class from offering that choice to the
calling code as well, by providing a public member function for
either method. (It could, for instance, use shallow copying by
default, but offer a deepCopy() member function that deep-copies
the data for the object in question if it's being currently shared
among several objects.)

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Richard

unread,
Aug 20, 2015, 1:57:24 PM8/20/15
to
[Please do not mail me a copy of your followup]

Paul <peps...@gmail.com> spake the secret code
<92d74fb1-3877-4de9...@googlegroups.com> thusly:

>I realise that this was not intended as a c++ question, but I can't see
>a way to do this in c++ because of the huge generality of the question,
>even though I have a basic understanding of deep copying. Can anyone
>help me get an answer in c++ (or help me understand the answers that are
>already provided.)?

In C++, whether one is doing a "shall copy" or a "deep copy" is up to
the implementor of the data structure in how they implement their copy
constructor/assignment operation or in other member functions that
they provide.

For example, here is a structure that will do a "deep copy" when you
use the compiler's supplied copy constructor/assignment:

#include <iostream>
#include <memory>
#include <string>

#include <string>

struct p
{
int i;
std::string s;
};

void doing_deep_copy()
{
p p1{10, "hello, there!"};
p p2 = p1; // deep copy
p2.s = "goodbye!";
std::cout << "p1.s = '" << p1.s << "'\n";
std::cout << "p2.s = '" << p2.s << "'\n";
}

struct q
{
int i;
std::shared_ptr<std::string> s;
};

void doing_shallow_copy()
{
q q1{10, std::make_shared<std::string>("hello, there!")};
q q2 = q1; // shallow copy
*q2.s = "goodbye!";
std::cout << "q1.s = '" << *q1.s << "'\n";
std::cout << "q2.s = '" << *q2.s << "'\n";
}

int main()
{
doing_deep_copy();
doing_shallow_copy();
return 0;
}

The output of this program is:

p1.s = 'hello, there!'
p2.s = 'goodbye!'
q1.s = 'goodbye!'
q2.s = 'goodbye!'

doing_deep_copy is a "deep copy" because after p2 is constructed, it
isn't sharing the string p2.s with p1.s -- they are distinct strings.

However, doing_shallow_copy is a "shallow copy" when you use the
compiler's supplied copy constructor/assignment because it just copies
the members over and the member is a shared pointer to a string.

If you want struct q to have deep copy semantics, you can either
override the compiler-supplied copy constructor/assignment or you can
write a separate member function, most often called 'clone', that
explicitly implements the deep copy operation. Some folks prefer the
'clone' approach because when they see simple = style assignment they
can assume the same semantics as those supplied by the compiler:
memberwise copying.

Unlike a language like JavaScript, you don't have reflection
capabilities in C++, so you can't "dig into the object" being copied
in a generic way and recursively duplicate everything that implies
referenced storage.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Alf P. Steinbach

unread,
Aug 21, 2015, 8:47:35 AM8/21/15
to
On 19.08.2015 09:34, Paul wrote:
> A question asked in a job interview on deep copying is available here: http://www.careercup.com/question?id=6304195600711680
>
> I will repeat it here:
> BEGIN QUOTE
> Write a function called deepCopy that takes an object and creates a deep copy of it.
> var newObj = deepCopy(obj);
> (can't use JSON, can't use prototype)
> END QUOTE
>
> I realise that this was not intended as a c++ question, but I can't
> see a way to do this in c++ because of the huge generality of the
> question, even though I have a basic understanding of deep copying.


template< class Type >
auto deepCopy( Type&& o ) -> std::remove_ref<Type> { return o; }


(Not sure of the remove_ref, look it up, but thereabouts)

This gives you a logical deep copy, which is all you need. E.g. with g++
old COW strings it will defer the actual copying and just increment a
ref count. Physical deep copying is, as you note, generally impossible
in a type-independent way.


Cheers & hth.,

- Alf

Mr Flibble

unread,
Aug 21, 2015, 10:28:16 AM8/21/15
to
On 21/08/2015 13:47, Alf P. Steinbach wrote:
> On 19.08.2015 09:34, Paul wrote:
>> A question asked in a job interview on deep copying is available here:
>> http://www.careercup.com/question?id=6304195600711680
>>
>> I will repeat it here:
>> BEGIN QUOTE
>> Write a function called deepCopy that takes an object and creates a
>> deep copy of it.
>> var newObj = deepCopy(obj);
>> (can't use JSON, can't use prototype)
>> END QUOTE
>>
>> I realise that this was not intended as a c++ question, but I can't
>> see a way to do this in c++ because of the huge generality of the
>> question, even though I have a basic understanding of deep copying.
>
>
> template< class Type >
> auto deepCopy( Type&& o ) -> std::remove_ref<Type> { return o; }

No need to use 'auto' here unless you are an autsy like Alf.

/Flibble
0 new messages