class baseDMA
{
private:
char* label;
int rating;
public:
baseDMA(const char* l="NULL", int r =0);
baseDMA(const baseDMA& rs);
virtual ~baseDMA();
baseDMA& operator=(const baseDMA& rs);
friend ostream& operator<<(ostream& os, const baseDMA& rs);
};
//Derivation classes without DMA
I don't need a destroyer
//Use an implicit copy generator
Use an implicit substitution operator
class lacksDMA : public baseDMA
{
private:
enum { COL_MEN = 40 };
char color[COL_MEN];
public:
lacksDMA(const char* c="blank", const char*l="NULL", int r = 0);
lacksDMA(const char* c, const baseDMA& rs);
friend ostream& operator<<(ostream& os,const lacksDMA& ls);
};
int main()
{
lacksDMA balloon2 (balloon); // Assume ballon is a lacksDMA object, predefined, initialized
return 0;
}
Hi, everyone I have no way of knowing, so I'm asking because I'm looking here and there and I don't get an answer, so I think it's the last time.
It's about copying between members when calling the default copy generator. If the member is an array, I would like to know how it is copied.
The above source describes the definition of a copy generator, a large operator, and a destroyer depending on whether or not dynamic memory placement is used in the derived class.
Because the source does not use dynamic memory in the derived class, the derived class only needs the default copy generator, the default copy generator, and the default substitution operator.That means you don't have to define these three things separately
But the problem is that the default copy generator is curious.If you look at the main function, The racksDMA object balloon is initializing balloo2.
Here, since lacksDMA does not require a copy generator, for initialization of balloo2, The balloon object is used and therefore the default copy generator is called.
The copy creator learned that copies are made between members.But if the member variable is an array, I wonder how the copy is made.
Simple inta = b; It would be nice if it was this simple substitution, but wouldn't it work in an array? For example,
char a[10] = "School";
char b[10];
b = a; //Error
Isn't this the wrong code, for example, the source? To copy from this char array, use the strcpy() or strncpy() function, or use the iterations You should use a method such as substituting or etc.
Likewise, how is the member variable copied in the stacksDMA? Is it possible to copy internally by using strcpy or strncpy functions?
I thought copying by member was a concept of copying due to simple college entrance, but now that I think about the arrangement, I think this is not right. Please. I'm so curious.
c++ visual-studio-2010 constructor array
The process differs depending on the compiler, depending on whether the member variable is a POD type or a class type with a copy generator.
Also, auto-generated copy constructors may not be represented in the C++ language. These are clearly visible in assembly language and can be helpful for understanding.
First, let's express the automatically generated copy constructor directly in C++ and then show the assembly code.
For the POD type, copy via memcpy() similar to strcpy(). In other words, in the case of the code you mentioned, you can think that the copy generator below is automatically created.
lacksDMA::lacksDMA(lacksDMA const& rhs)
: : baseDMA(rhs)
{
std::memcpy(color, rhs.color, sizeof(color));
}
Let's look at the assembly code to make sure what I said is correct.
The following conversion to the code assembly code you created is located at https://godbolt.org/g/V6UpcV. If you look at the assembly code, you can see the following:
lacksDMA::lacksDMA(lacksDMA const&):
push rbp
mov rbp, rsp
sub rsp, 16
mov QWORD PTR [rbp-8], rdi
mov QWORD PTR [rbp-16], rsi
mov rax, QWORD PTR [rbp-8]
mov rdx, QWORD PTR [rbp-16]
mov rsi, rdx
mov rdi, rax
call baseDMA::baseDMA(baseDMA const&)
mov edx, OFFSET FLAT:vtable for lacksDMA+16
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax], rdx
mov rcx, QWORD PTR [rbp-8]
mov rsi, QWORD PTR [rbp-16]
mov rax, QWORD PTR [rsi+20]
mov rdx, QWORD PTR [rsi+28]
mov QWORD PTR [rcx+20], rax
mov QWORD PTR [rcx+28], rdx
mov rax, QWORD PTR [rsi+36]
mov rdx, QWORD PTR [rsi+44]
mov QWORD PTR [rcx+36], rax
mov QWORD PTR [rcx+44], rdx
mov rax, QWORD PTR [rsi+52]
mov QWORD PTR [rcx+52], rax
nop
leave
ret
As you can see, there is a part called lacksDMA:lacksDMA (lacksDMA const&):
which is the copy generator that the compiler automatically generated.
The content below that becomes the content of the corresponding copy creator.
There is call baseDMA::baseDMA (baseDMA const&)
in the content, where you call the copy constructor of the parent class baseDMA
.
The code below will then be the assembly that copies the array.
movrax, QWORD PTR [rsi+20];// read balloon.color[0] to balloon.color[7]
movedx, QWORD PTR [rsi+28];// balloon.color[8] ~ balloon.color[15] Read
mov QWORD PTR [rcx+20], rx;// Write the read value to balloon2.color[0] ~ balloon2.color[7]
mov QWORD PTR [rcx+28], rdx;// Write the read value to balloon2.color[8] ~ balloon2.color[15]
moverax, QWORD PTR [rsi+36];// read balloon.color[16] to balloon.color[23]
movedx, QWORD PTR [rsi+44];// read balloon.color[24] to balloon.color[31]
mov QWORD PTR [rcx+36], rx;// Write the read value to balloon2.color[16] ~ balloon2.color[23]
mov QWORD PTR [rcx+44], rdx;// Write the read value to balloon2.color[24] to balloon2.color[31]
moverax, QWORD PTR [rsi+52];// read balloon.color[32] to balloon.color[39]
mov QWORD PTR [rcx+52], rx;// Write the read value to balloon2.color[32] to balloon2.color[39]
In this assembly, the array is read in 8 bytes (QWORD) and copied over a total of 5 times. The reason why it is copied in QWORD units rather than in 1-byte units is that it performs better.
At first, I told you that I would call memcpy(), but as you can see, the copy command was made five times. This is because the compiler determined that it would be faster to copy five times in a row than to invoke memcpy().
So in what situation can we call memcpy()? If you increase the color
array size to 512, the following results are obtained.
mov eax, eax
mov rsi, rdx
mov rcx, rax
rep movsq
https://godbolt.org/g/dPHtFn If you look here, you can see that memcpy() is converted as follows, indicating that a code similar to that of changing color
to 512 above.
mov ecx, 512
mov rdi, rax
mov rsi, rdx
rep movsq
This means that the amount of memory you're going to copy will determine whether to write memcpy().
For POD, memcpy() is used because you can copy member variables simply by copying memory. However, for class types, there is a copy generator that the programmer can create himself, and the way the copy is copied depends on what you create.
Therefore, when automatically generated copy constructors copy a member variable with an array of class types, they call the copy constructors of each array element to proceed with the copy creation.
I will explain based on the code below.
#include <string>
class Array
{
public:
std::string elements[100];
};
int main()
{
Array a1;
Array a2(a1);
return 0;
}
Because elements
is an array with class-type elements, a copy generator using memcpy()
like POD is not created, and a code is automatically generated to copy each element as shown below.
Array::Array(Array const& rhs)
{
// Elements are allocated only memory space and the default constructor is not called home
for (std::size_t i = 0; i < 100; ++i)
{
new (&elements[i]) std::string(rhs.elements[i]);
}
}
At this time, elements
is not created by calling the default constructor, and only memory space is allocated.
The auto-generated constructor circulates the loop and calls the copy constructor of the element, such as new (&elements[i]) std:string(rhs.elements[i]);
.
If you look at the assembly code (https://godbolt.org/g/WQDCEw), you will find the following:
Array::Array(Array const&):
push rbp
mov rbp, rsp
push r14
push r13
push r12
push rbx
sub rsp, 16
mov QWORD PTR [rbp-40], rdi
mov QWORD PTR [rbp-48], rsi
mov rbx, QWORD PTR [rbp-40]
mov r12d, 99
mov r13, QWORD PTR [rbp-48]
mov r14, rbx
.L10:
test r12, r12
js .L15
mov rsi, r13
mov rdi, r14
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
add r14, 32
add r13, 32
sub r12, 1
jmp .L10
mov r13, rax
test rbx, rbx
je .L12
mov eax, 99
sub rax, r12
sal rax, 5
lea r12, [rbx+rax]
.L13:
cmp r12, rbx
je .L12
sub r12, 32
mov rdi, r12
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()
jmp .L13
.L12:
mov rax, r13
mov rdi, rax
call _Unwind_Resume
.L15:
nop
add rsp, 16
pop rbx
pop r12
pop r13
pop r14
pop rbp
ret
Here, the code below goes around the loop and calls the copy generator of each array element.
.L10:
test r12, r12
js .L15
mov rsi, r13
mov rdi, r14
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
add r14, 32
add r13, 32
sub r12, 1
jmp .L10
testr12, r12
and js.L15
to check if it has arrived at the end of the loop (whether the last element has been created or not), and if it has arrived at the end, .You will jump with the L15
label.
If you still have elements of the array to be created, call std:_cxx11:::basic_string<char, std::char_traces<char>, std:allocator<char> >::basic_string(st:__cxx11;character>::character>::character>:::character>character>::character>character>::::character>character>:::character>
Repeat the loop by jumping to the location where the
testr12, r12
code is located via jmp.L10
.
The automatically generated copy constructors differ in content from compiler to compiler and depend on the definition of the class.
Generally speaking, an array with a POD type as an element copies the array via memcpy() and an array with a class type as an element circulates a loop and invokes a copy constructor for each element.
567 Who developed the "avformat-59.dll" that comes with FFmpeg?
886 When building Fast API+Uvicorn environment with PyInstaller, console=False results in an error
567 rails db:create error: Could not find mysql2-0.5.4 in any of the sources
599 GDB gets version error when attempting to debug with the Presense SDK (IDE)
© 2024 OneMinuteCode. All rights reserved.