object copy with reference

P

Philipp Kraus

Hello,

I need a tip / hint for solving the following problem:

I have a class method that is run in different threads:
myclass::mythreadmethod( mysuperclass& )

mysuperclass is a reference variable, that is used during the thread is
running.
Anyway the method should be myclass::mythreadmethod( mysuperclass ), so that
each running thread has a own local copy of the object, but I can't
switch the parameter
because the method is derivated of another class.

I need in the method a local (deep-copy) of my object. So I create a
clone method like
myclass::mythreadmethod( mysuperclass& pobj )
{
mysuperclass& lobj = p_obj.clone();
}

In this case I get the compiler error, that I try to set up a temporary
assignment.

The try to do it like
myclass::mythreadmethod( mysuperclass& pobj )
{
mysuperclass& lobj;
p_obj.clone(lobj);
}
create the message l_obj isn't initializate.

Does anyone has some tips to create a working solution? The perfect solution
should be a deep-copy of the pobj reference

Thanks

Phil
 
V

Victor Bazarov

I have a class method that is run in different threads:
myclass::mythreadmethod( mysuperclass& )

Is there any relationship between 'myclass' and 'mysuperclass'?
mysuperclass is a reference variable, that is used during the thread is
running.

OK, nothing strange here so far.
Anyway the method should be myclass::mythreadmethod( mysuperclass ), so
that
each running thread has a own local copy of the object, but I can't
switch the parameter
because the method is derivated of another class.

So, the other class (from which your 'myclass' is derived) requires the
argument to be a reference to a non-const object. Seems OK. You can
implement your own

myclass::mythreadmethod_impl(mysuperclass)

by overriding the 'mythreadmethod' this way:

returntype myclass::mythreadmethod(mysuperclass& o)
{
mysuperclass local_o(o);
return this->mythreadmethod_impl(local_o);
}

(although, strictly speaking, the creation of local_o isn't necessary,
it's done here just for illustrating the fact of copying the 'o').
I need in the method a local (deep-copy) of my object. So I create a
clone method like
myclass::mythreadmethod( mysuperclass& pobj )
{
mysuperclass& lobj = p_obj.clone();
}

In this case I get the compiler error, that I try to set up a temporary
assignment.

"Temporary assignment"? What's that?

And what error do you get?
The try to do it like
myclass::mythreadmethod( mysuperclass& pobj )
{
mysuperclass& lobj;

You cannot declare a local object of type reference without initializing
it. That ought to be flagged by the compiler as an error.
p_obj.clone(lobj);
}
create the message l_obj isn't initializate.

Does anyone has some tips to create a working solution? The perfect
solution
should be a deep-copy of the pobj reference

See above. It does depend, however, on how 'mysuperclass' is defined.

V
 
P

Philipp Kraus

Is there any relationship between 'myclass' and 'mysuperclass'?

No, nothing, exception a myclass object calls methods in the
mysuperclass object.
So, the other class (from which your 'myclass' is derived) requires the
argument to be a reference to a non-const object. Seems OK. You can
implement your own

myclass::mythreadmethod_impl(mysuperclass)

by overriding the 'mythreadmethod' this way:

returntype myclass::mythreadmethod(mysuperclass& o)
{
mysuperclass local_o(o);
return this->mythreadmethod_impl(local_o);
}

(although, strictly speaking, the creation of local_o isn't necessary,
it's done here just for illustrating the fact of copying the 'o').


That's nice, i will try that. But one question, mysuperclass is a pure
virtual class, so I can't instanciate it directly (sorry, i've forgot
this information in my first posting)

Thanks

Phil
 
P

Philipp Kraus

Is there any relationship between 'myclass' and 'mysuperclass'?


OK, nothing strange here so far.


So, the other class (from which your 'myclass' is derived) requires the
argument to be a reference to a non-const object. Seems OK. You can
implement your own

myclass::mythreadmethod_impl(mysuperclass)

by overriding the 'mythreadmethod' this way:

returntype myclass::mythreadmethod(mysuperclass& o)
{
=> mysuperclass local_o(o); <=
return this->mythreadmethod_impl(local_o);
}

the marked => <= call is my problem, bevause mysuperclass is pure
virtual, so I can't do exactly this. I would like to clone "o"
(deep-copy) to a local
variable, but I know that o is a derivate object of mysuperclass. So I
have add a pure virtual method "clone" to the superclass mysuperclass,
that
must be implementated within the derivate class like:

mysuperclass& local_o = o.clone()

so local_o gets now a fully own reference to a new o object. The
problem is the returning type of clone, if I return a mysuperclass& and
do within
clone something like
mysuperclass& clone( void ){
return myderivateclass; // call the default constructor and
returns the object with myderivateclass : public mysuperclass
}
the compiler breaks with the error temporary assignment, because the
object is create on the local stack frame and after the clone the
object is removed.

If I implementate the clone like
void clone( mysuperclass& ref) {
ref = myderivateclass;
}

and call the clone in the context:
mythreadmethod( mysuperclass& o) {
mysuperclass local_o; //*
o.clone(local_o);
}

the * creates the warning that local_o isn't initialisized, if I use a
mysuperclass& the compiler create the error, that I can't use
an empty reference

Thanks

Phil
 
G

Goran

the marked => <= call is my problem, bevause mysuperclass is pure
virtual, so I can't do exactly this. I would like to clone "o"
(deep-copy) to a local
variable, but I know that o is a derivate object of mysuperclass. So I
have add a pure virtual method "clone" to the superclass mysuperclass,
that
must be implementated within the derivate class like:

mysuperclass& local_o = o.clone()

so local_o gets now a fully own reference to a new o object. The
problem is the returning type of clone, if I return a mysuperclass& and
do within
clone something like
mysuperclass& clone( void ){
    return myderivateclass;  // call the default constructor and
returns the object with myderivateclass : public mysuperclass}

the compiler breaks with the error temporary assignment, because the
object is create on the local stack frame and after the clone the
object is removed.

If I implementate the clone like
void clone( mysuperclass& ref) {
     ref = myderivateclass;

}

and call the clone in the context:
mythreadmethod( mysuperclass& o) {
     mysuperclass local_o;  //*
     o.clone(local_o);

}

the * creates the warning that local_o isn't initialisized, if I use a
mysuperclass& the compiler create the error, that I can't use
an empty reference

I think you should take a look at ICloneable in Java and .NET. What
you want is a copy of an object without knowing its type at
compilation time. You can add "clone" to abstract your base class,
however, you must create the object from there, that is, clone()
should be:

struct base
{
virtual base* clone() const = 0;
};

From there, a derived class simply does:

struct derived : public base
{
virtual base* clone() const { return new derived(*this); }
derived(const derived& rhs) { ... }
};

Finally, as I said, you should look at ICloneable. This is because
"cloning" you need happens so often that it's good to formalize it. It
requires that you know a base class (there's always one in e.g. Java,
and in a lot of C++ frameworks, too). So that's a good start, if
applicable.

One last thing: since you have threads, copy-construction must be
thread-safe (i.e, you need a mutex in derived(const derived& rhs)).

Goran.

Goran.
 
Q

Qi

and call the clone in the context:
mythreadmethod( mysuperclass& o) {
mysuperclass local_o; //*
o.clone(local_o);
}

the * creates the warning that local_o isn't initialisized, if I use a
mysuperclass& the compiler create the error, that I can't use
an empty reference

Usually clone returns an object on the heap.

MyObject * clone(const MyObject & other) {
return new MyObject(other);
}

If you want to initialize a value, it's better to be "assign".

void assign(const MyObject & from) {
this->value = from.value;
}

Or vice versa,

void assignTo(MyObject * to) {
to->value = this->value;
}

Because clone and assign determine the type at runtime,
you can't return object by value.
If youc an determine the type at compile time, you don't
need clone, but just copy the object...
 
W

Werner

Hello,

I need a tip / hint for solving the following problem:

I have a class method that is run in different threads:
myclass::mythreadmethod( mysuperclass& )

mysuperclass is a reference variable, that is used during the thread is
running.
Anyway the method should be myclass::mythreadmethod( mysuperclass ), so that
each running thread has a own local copy of the object, but I can't
switch the parameter
because the method is derivated of another class.

I need in the method a local (deep-copy) of my object. So I create a
clone method like
myclass::mythreadmethod( mysuperclass& pobj )
{
    mysuperclass& lobj = p_obj.clone();

}

In this case I get the compiler error, that I try to set up a temporary
assignment.

The try to do it like
myclass::mythreadmethod( mysuperclass& pobj )
{
    mysuperclass& lobj;
   p_obj.clone(lobj);}

create the message l_obj isn't initializate.

Does anyone has some tips to create a working solution? The perfect solution
should be a deep-copy of the pobj reference

Thanks

Phil

How about making mysuperclass a pointer (or a smart pointer of some
kind), then you can initialize it to zero (or in the case of smart_ptr
it happens automatically). I'd use scoped_ptr in this case..., but as
example I'd this use a bald pointer...

struct MySuper
{
virtual MySuper* clone() const = 0;

//... rest of interface

//... lets not forget this...
virtual ~MySuper() = 0;
};



class Thread
{
public:
Thread();
~Thread();
void associate( MySuper& super );

private:
MySuper* super_;
};

//x.cpp
void Thread::associate( MySuper& super )
{
super_ = super.clone();
}

Thread::Thread()
: super_() //Don't forget this for bald pointers...
{ }

Thread::~Thread()
{
delete super_;
}
 
W

Werner

How about making mysuperclass a pointer (or a smart pointer of some
kind), then you can initialize it to zero (or in the case of smart_ptr
it happens automatically). I'd use scoped_ptr in this case..., but as
example I'd this use a bald pointer...
[snip]

I've decided to throw in a smart pointer example too:


#include <memory>

struct MySuper
{
virtual MySuper* clone() const = 0;

//... rest of interface

//... lets not forget this...
virtual ~MySuper() = 0;
};



class Thread
{
public:
Thread();
~Thread();
void associate( MySuper& super );

private:
std::auto_ptr<MySuper> super_;
};

//x.cpp
void Thread::associate( MySuper& super )
{
super_.reset( super.clone() );
}

Thread::Thread()
{ }

Thread::~Thread()
{
}

I've used auto_ptr in scoped_ptr's stead just because
for you it might be readily available, whereas scoped_ptr
(or a version thereof) you can get from www.boost.org, but
your version of STL might not support scoped_ptr out of the
box.

Kind regards,

Werner
 
P

Philipp Kraus

How about making mysuperclass a pointer (or a smart pointer of some
kind), then you can initialize it to zero (or in the case of smart_ptr
it happens automatically). I'd use scoped_ptr in this case..., but as
example I'd this use a bald pointer...

Thanks, I#M using smart-pointer, i don't see the solution with pointer :p
 
W

Werner

Thanks, I#M using smart-pointer, i don't see the solution with pointer :p

Just be careful of auto_ptr in general. If possible, use scoped_ptr,
otherwise be sure to overload your copy constructor and assignment
operator.

Kind regards,

Werner
 
W

Werner

Just be careful of auto_ptr in general. If possible, use scoped_ptr,
otherwise be sure to overload your copy constructor and assignment
operator.

Kind regards,

Werner

I meant to say "override" the copy constructor / assignment operator,
not "overload" (for those who are linguistically pedantic - I realize
the difference).

Kind regards,

Werner
 
S

SG

I meant to say "override" the copy constructor / assignment operator,
not "overload" (for those who are linguistically pedantic - I realize
the difference).

Linguistic pedants would say "declare", I guess. Overriding is
something specific to virtual functions.

SG
 
W

Werner

Linguistic pedants would say "declare", I guess. Overriding is
something specific to virtual functions.

SG

:). Agreed. Declare it, and declare it private (without
definition) if you want to prohibit copying and assignment,
or inherit from boost::noncopyable (which shows intent), or
just use a scoped_ptr, which is not copyable by default.

Apologies for my lack of linguistic accuracy. Thanks for
the correction.

Kind regards,
 

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

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,710
Latest member
bernietqt

Latest Threads

Top