Use operator new of C ++ to call constructor multiple times for the same object

Source: Internet
Author: User

Struct stest

{

Stest (void)

{

++ Icount;

}

 

Int icount;

}

 

Int main (void)

{

Stest OBJ;

OBJ. icount = 0;

New (static_cast <void *> (& OBJ) stest ();

 

Return 0;

}

 

Just write an example to illustrate the problem.

The above red code calls the constructor. to count the constructor, the Code initialized to 0. The blue section is the topic before calling the constructor again. First, operator new (size_t, void *) thow () is called (). The prototype of this function is:

Inline void * _ cdecl operator new (size_t, void * _ Where) _ throw0 ()
{// Construct array with placement at _ Where
Return (_ Where );
}

There is no new space. Return directly! Why is stest () followed? And the syntax is correct. After the new operator is executed. The return value is the address of the OBJ object we passed in. Since stest () is written, it must be called.

But what about creating a new object? Or is it the original object? Here, we can only analyze it in disassembly.

First, let's look at the main function:

0020.a60 push EBP
00347a61 mov EBP, ESP
00366a63 push 0 ffffffffh
0020.a65 push offset _ ehhandler $ _ main (425954 H)
0020.a6a mov eax, dword ptr fs: [00000000 H]
0020.a70 push eax
0020.a71 mov dword ptr fs: [0], ESP
00347a78 sub ESP, 0e8h
00366a7e push EBX
00366a7f push ESI
00417a80 push EDI
00347a81 Lea EDI, [ebp-0F4h]
0020.a87 mov ECx, 3ah
00417a8c mov eax, 0 cccccccch
0020.a91 rep STOs dword ptr [EDI]
002.16a93 Lea ECx, [OBJ]
00347a96 call stest: stest (4115dch)
0020.a9b mov dword ptr [OBJ], 0
0020.aa2 Lea eax, [OBJ]
00417aa5 push eax
00417aa6 Push 4
0010000aa8 call operator new (411096 H)
00w.aad add ESP, 8
00417ab0 mov dword ptr [ebp-0E0h], eax // return value of the new operator
00347ab6 mov dword ptr [ebp-4], 0
00127abd cmp dword ptr [ebp-0E0h], 0
001_ac4 je main + 79 H (1_ad9h)
0020.ac6 mov ECx, dword ptr [ebp-0E0h] // returns the value to ECx
00366acc call stest: stest (4115dch) // call the constructor
0020.ad1 mov dword ptr [ebp-0F4h], eax
00417ad7 JMP main + 83 H (417ae3h)
0020.ad9 mov dword ptr [ebp-0F4h], 0
0020.ae3 mov ECx, dword ptr [ebp-0F4h]
0020.ae9 mov dword ptr [ebp-0ECh], ECx
0020.aef mov dword ptr [ebp-4], 0 ffffffffh
00366af6 XOR eax, eax
00366af8 push edX
00366af9 mov ECx, EBP
00366afb push eax
00417afc Lea edX, DS: [rjb27h]
00366b02 call @ ILT + 480 (@ _ rtc_checkstackvars @ 8) (4111e5h)
00366b07 pop eax
00366b08 pop edX
00366b09 mov ECx, dword ptr [ebp-0Ch]
0020.b0c mov dword ptr fs: [0], ECx
00366b13 pop EDI
00366b14 pop ESI
00366b15 pop EBX
00366b6 add ESP, 0f4h
00366b1c cmp ebp, ESP
00366b1e call @ ILT + 1095 (_ rtc_checkesp) (41144ch)
00366b23 mov ESP, EBP
00366b25 pop EBP
00366b26 RET

 

First, the red command calls the new operator. After that, put the returned value eax in the ebp-0E0h, and the second blue command gave the value inside ECx. The purpose here is to pop ECx In the constructor. This is related to the disassembly procedure of calling member functions by class objects. First, the object address is assigned to ECx. A member function has two more commands than a common function. Push ECx and pop ECx. Let's take a look at the disassembly code of the stest constructor:

00411d90 push EBP
00411d91 mov EBP, ESP
00411d93 sub ESP, 0cch
00411d99 push EBX
00411d9a push ESI
00411d9b push EDI
00411d9c push ECx
00411d9d Lea EDI, [ebp-0CCh]
00411da3 mov ECx, 33 H
00411da8 mov eax, 0 cccccccch
00411dad rep STOs dword ptr [EDI]
00411daf pop ECx
00411db0 mov dword ptr [ebp-8], ECx
00411db3 mov eax, dword ptr [this]
00411db6 mov ECx, dword ptr [eax]
00411db8 add ECx, 1
00411dbb mov edX, dword ptr [this]
00411dbe mov dword ptr [edX], ECx
00411dc0 mov eax, dword ptr [this]
00411dc3 pop EDI
00411dc4 pop ESI
00411dc5 pop EBX
00411dc6 mov ESP, EBP
00411dc8 pop EBP
00411dc9 RET

The red push is to let ECx out and execute the blue mov ECx, 33 H. There is no way for others to save their values to the pressure stack first. After Others use up, the red pop ECX will be executed. Re-pop the value of the pushed ECx to ECx! Let's look at the following two green commands and give ECx to the [ebp-8]. Here is the address of the first byte of the struct object. I will not talk much about the principle! This Pointer Points to the address of the newly passed OBJ object. Then, add 1. Of course, you can perform other operations. Haha. The constructor is called multiple times!

This is generally used to apply for an existing space:

Template <class ty>
Class alga_api calgaallocator
{
Public:
Calgaallocator (void ){}
Virtual ~ Calgaallocator (void ){}

Public:
Ty * allocate (size_t size)
{
Return (TY *) internal_new (size * sizeof (TY ));
}

Void deallocate (TY * PTR)
{
Internal_delete (PTR );
}

Void construct (TY * PTR, const ty & ELEM)
{
New (void *) PTR) ty (ELEM );
}

Void destruct (TY * PTR)
{
PTR-> ~ Ty ();
}

Protected:
Virtual void * internal_new (size_t size)
{
Return operator new (size );
}

Virtual void internal_delete (void * PTR)
{
Operator Delete (PTR );
}
};

A piece of code in my engine! I can explain the principle clearly. Sleeping ~~~

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.