What instance / move constructor / operator to define simple structures?

My program uses a simple Rect structure, which is defined as

 struct Rect { int x1, y1, x2, y2; Rect() : x1(0), y1(0), x2(0), y2(0) { } Rect(int x1, int y1, int x2, int y2) : x1(x1), y1(y1), x2(x2), y2(y2) { } }; 

Should I define a copy / move constructor or assignment operator, or can I rely on the compiler to automatically generate them? The question is in the context of speed and usage (for example, a move constructor can affect the speed of a program).

The constructors and operator are very repetitive, so it would be nice if I can rely on the compiler to automatically create them.

  Rect(const Rect& r) : x1(r.x1), y1(r.y1), x2(r.x2), y2(r.y2) { } Rect(Rect&& r) : x1(r.x1), y1(r.y1), x2(r.x2), y2(r.y2) { } Rect& operator = (const Rect& r) { x1 = r.x1; y1 = r.y1; x2 = r.x2; y2 = r.y2; } 
+4
source share
4 answers

Q1: Can you rely on a compiler to automatically generate data?

Yes (in your example). See C ++ 11 Standard (section 12) or the article Implicit Wont Go! (good chart near the end). To summarize (and simplify), all of the following special member functions will be automatically generated (implicitly declared and defined as default):

  • Destructor - because you did not declare it.
  • Copy Constructor - because you did not declare it with either MC or MAO.
  • Copy assignment operator - because you did not declare it with either MC or MAO.
  • Move the constructor - because you did not declare it with D, CC, CAO, or MAO.
  • Move Assignment Operator - because you did not declare it, neither in D, CC, CAO and MC.

(I used ugly initials only to save list items one line at a time.) In addition to the β€œbecause” above, for all but Destructor, there is an additional restriction that the generated default values ​​must have, that is, all given members must be copied (for the Central Committee and the CAO) or movable (for the MS and MAO). (Actually, the exact rules are a bit more complicated, but I don't want to rephrase the standard here.)

Q2: Are auto-generated functions performed correctly?

Yes (in your example). All your data members (here plain int s) have the correct copy / move semantics (their copy / move constructors and assignment operators do the right thing, and those Rect generated for Rect will call them).

Q3: In any case, should they be determined manually?

I do not see this as an advantage (in your example) and potential problems (as in your example, see comments).

+6
source

You can relay in the compiler, since your data members are built-in types, so a copy of your object can be created using a phased copy. This is true if you do not define a copy / move constructor or assignment operator. You may need them if you have a pointer as a data member.

+1
source

you do not need to write an explicit copy constructor for assignment so that the members of your Rect structure are all types of C ++ buildin, so the compiler will generate a bitwise copy constructor. In your code, I think you can rely on your compiler completely.

+1
source

If you want to be verbose for some reason, you can declare them the default for self-documentation as follows:

 struct Rect { int x1, y1, x2, y2; Rect () : Rect( 0, 0, 0, 0 ) { } Rect ( int x1, int y1, int x2, int y2 ) : x1(x1), y1(y1), x2(x2), y2(y2) { } // Rect is Copy/Move Constructible and Assignable Rect( Rect const & ) = default; Rect( Rect && ) = default; Rect& operator= ( Rect const & ) = default; Rect& operator= ( Rect && ) = default; }; 

Also mentions a default constructor that reuses the full one thanks to delegate constructors

+1
source

Source: https://habr.com/ru/post/1499920/


All Articles