Re: How to create a shallow copy without calling a constructor?
On Jan 3, 5:54 pm, viboes <vicente.bo...@wanadoo.fr> wrote:
Hello,
I need to create a cache of a transactional object without using the
new operator nor the copy constructor of the class. This cache needs
only to copy the raw memory of the copied instance, is for that I have
called it shallow_clone
The following will create a deep copy and don't respect my
requirements
class C {
public:
C* shallow_clone() {
return new C(*this);
}
};
Let's get terminology clear first... Deep versus shallow copy is
usually explained like this: http://en.wikipedia.org/wiki/Object_copy
What strikes me as strange is that you are employing operator new.
This is unwarranted when speaking only about deep/shallow copy
distinction. So the way to make what is commonly known as a deep copy
is both
C copy(original);
AND
C* pcopy = new C(original);
IOW, storage doesn't matter, at least unless you start with derivation
and polymorphism.
Shallow copy means that you want a copy where only part of original
instance data. Typically, in a shallow copy, you don't want a copy of
embedded or pointed-to objects. For that, there is no mechanism in C+
+, and trying to use memcpy is most usually a HUGE MISTAKE: you are
e.g. creating dangling pointers, you are breaking reference counting
for objects that do it, (strings come to mind) etc.
So the problem with shallow copy is that "shallow" means different
things in different contexts, that is, which class members are
"shallow", and which are "deep". That's for your design to decide.
Consequence of that is that you have to create your own shallow copy
function and avoid standard copy constructors and assignments. They
are most usually deep copies, so leave them for that.
Conclusion:
You have only one reasonable path: decide what constitutes a "shallow"
copy and make a function that does that, e.g.
class shallow_piece
{
int i, j, k; // Shallow
};
class C
{
shallow_piece shallow;
vector<other_class> deep;
// Special conversion ctor that acts as a shallow-copy-ctor.
// If shallow_piece is POD, it's effectively as fast as memcpy.
C(const shallow_piece& original) : shallow(original) {}
};
and then:
C original;
C shallow_copy(original.shallow);
C deep_copy(original);
I repeat: whether the result is on the heap or not is orthogonal to
the question of deep versus shallow. But, if you have derivation, then
it's very likely that shallow_piece idea is less useful. You then have
to have shallow_copy function that returns heap-based instances, and
each derived class decides what members are shallow (typically, it
will take base class "shallow members" and add one or two of it's
own). You can still employ shallow_piece idea e.g. like this, at a
cost of using heap for "shallow" part:
class shallow_piece_base {etc.};
class C_base
{
shallow_piece_base* p_shallow;
virtual C_base* shallow_copy() const;
};
class shallow_piece_derived : public shallow_piece_base {etc.};
class C : public C_base
{
// inherited p_shallow always points to shallow_piece_derived.
C(const shallow_piece_derived& shallow) : p_shallow(new
shallow_piece_derived(shallow)) {}
virtual C_base* shallow_copy() const { return new C_base
(*p_shallow); };
};
If your concern is speed, there's two things to consider: measure
whether it's faster to copy stuff around or to share heap pointers.
But that __hugely__ depends on data sizes and your actual code the way
it's running "in production" (that is, a simple test program might be
misleading).
I have looked at uninitialized_copy but if I have understood it
correctly, it calls the copy constructor.
I have tried with
class C {
public:
C* shallow_clone() {
C* p = reinterpret_cast<C>(new char[sizeof(C)]);
if (p==0) {
throw std::bad_alloc();
That p==0 is just poor C++. new throws unless nothrow is used.
Goran.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]