|
|
Home » Community » Coffee corner » How would you design a good copy/move semantics system?
How would you design a good copy/move semantics system? [message #44023] |
Mon, 15 December 2014 15:08  |
cbpporter
Messages: 1427 Registered: September 2007
|
Ultimate Contributor |
|
|
This is more of a question for people deeply familiar to the way copy-constructing works.
I was thinking of a system where:
- each class can have a copy and a move optionally
- copy works like the default copy constructor, except for classes where deep copies are needed
- move works pretty much the way it works in U++, but only destroys data that would be copied by a deep copy
- calling move on a class that does not have a move implemented will do a copy
- the rules apply based on class depth
This are the principles. I need to also do an implementation that has as low overhead as possible performance wise and that does not look particularly ugly.
|
|
|
|
|
|
Re: How would you design a good copy/move semantics system? [message #44147 is a reply to message #44145] |
Thu, 08 January 2015 01:16   |
Lance
Messages: 656 Registered: March 2007
|
Contributor |
|
|
Hi cbpporter:
Happy New Year!
c++11 is here and will stay. The features you required are part of c++11, which means you can use it without any(almost) extra effort.
The code you quoted is like this: if base class have a copy constructor, derived class' move constructor will use the base class copy constructor to construct the base part of a derived object unless explicitly delegated to another ctor. Sounds very complicated, maybe it's easier to use an example:
struct base
{
base() : buff(nullptr), buff_len(0u){}
// copy ctor
base(const base& b): buff_len(b.buff_len)
{
if(buff_len)
{
buff=new char[buff_len];
memcpy(buff,b.buff,buff_len);
}else
buff=nullptr;
}
// move ctor, essentially do what Upp-pick is supposed to do
base(base&& b):buff_len(b.buff_len), buff(b.buff)
{
b.buff_len=0u;
b.buff=nullptr;
}
private:
char * buff;
unsigned buff_len;
};
struct derived : public base
{
derived(): i(0){} // will call base::default ctor to consturct base part of *this;
derived(const derived& d) : i(d.i) {} // will call base::copy ctor to construct base part of *this;
derived(derived&& d): i(d.i){} // you may expect base::move ctor to be called to construct base part of *this.
// I do think the c++ committee should default to use base move ctor for derived move ctor.
// unfortunately, this is not the case. you have to explicitly delegate the construction of
// the base part of *this to base move ctor, with something like this:
//
// derived(derived&& d) : base(std::move(d)), i(d.i){}
//
// this is the point I was trying to make.
private:
int i;
};
HTH.
Lance
[Updated on: Thu, 08 January 2015 01:20] Report message to a moderator
|
|
|
Re: How would you design a good copy/move semantics system? [message #44149 is a reply to message #44049] |
Thu, 08 January 2015 11:23   |
 |
mirek
Messages: 14255 Registered: November 2005
|
Ultimate Member |
|
|
cbpporter wrote on Thu, 18 December 2014 12:55What I'm mostly interested in is what are the rules for guaranteeing a maximum invocation of move constructors in implicit situations, like when assigning or returning values.
U++ chose to have default copy to be move for this reason, right?
Originally, yes. But please note that the whole thing changed last year.
Now you have to be explicit, either 'pick' or 'clone' the source, with some exceptions (e.g. returning temporary). (Enforced in C++11, in C++0x it is backward compatible).
IMO, C++11 way, where move constructor is called "sometimes" based on context leads to using deep copy in unexpected situations.
|
|
|
|
Re: How would you design a good copy/move semantics system? [message #44166 is a reply to message #44163] |
Mon, 12 January 2015 19:06  |
 |
mirek
Messages: 14255 Registered: November 2005
|
Ultimate Member |
|
|
cbpporter wrote on Mon, 12 January 2015 11:21I was interested in this in general, not necessarily in the context of C++, but in the context of value based programming languages.
Well, ideologically speaking, I would say normally there are 2 types of entities:
- those than can be (deeply) copied, usually called "concrete types". Typically, not polymorphic, no abstraction. E.g. Color, Font, Value...
- those that do not have easy meaningful copy - say "identity types". Usually all polymorphic types fall into this category. E.g. File, Ctrl, ...
I like to say that U++ adds to the list 3rd type:
- containers. For these it makes sense to have both 'clone' (in case that they contain concrete types) and 'pick' semantics. 'pick', besides being optimization, nicely adds RAII compatible and MT friendly way to move identity types around.
[Updated on: Mon, 12 January 2015 19:07] Report message to a moderator
|
|
|
Goto Forum:
Current Time: Fri Apr 25 11:58:34 CEST 2025
Total time taken to generate the page: 0.01000 seconds
|
|
|