[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Question on auto_ptr, Which function will call first?

asm23

10/3/2008 4:00:00 PM

Hi, everyone, I'm studying the <<Thinking in C++>> volume Two. In
Chapter One, the example code : Auto_ptr.cpp
//-------------------------------------------------------
#include <memory>
#include <iostream>
#include <cstddef>
using namespace std;

class TraceHeap {
int i;
public:
static void* operator new(size_t siz) { //*****NOTE A
void* p = ::operator new(siz);
cout << "Allocating TraceHeap object on the heap "
<< "at address " << p << endl;
return p;
}
static void operator delete(void* p) {
cout << "Deleting TraceHeap object at address "
<< p << endl;
::operator delete(p);
}
TraceHeap(int i) //*******NOTE B
: i(i)
{
;
}
int getVal() const { return i; }
};



int main() {
auto_ptr<TraceHeap> pMyObject(new TraceHeap(5));
cout << pMyObject->getVal() << endl; // Prints 5
}
//------------------------------------------------------------------

My question is :

In My code: which code will be called first? The *NOTE A* or *NOTE B* ?
And Why?

I'm debugging through this code and found that *NOTE A* will called
first. Can someone explained it?
When I trace into the *new* function, the *siz* value is 4. I don't know
why it will be 4?

Thank you for reading my message.


16 Answers

Victor Bazarov

10/3/2008 4:18:00 PM

0

asm23 wrote:
> Hi, everyone, I'm studying the <<Thinking in C++>> volume Two. In
> Chapter One, the example code : Auto_ptr.cpp
> //-------------------------------------------------------
> #include <memory>
> #include <iostream>
> #include <cstddef>
> using namespace std;
>
> class TraceHeap {
> int i;
> public:
> static void* operator new(size_t siz) { //*****NOTE A
> void* p = ::operator new(siz);
> cout << "Allocating TraceHeap object on the heap "
> << "at address " << p << endl;
> return p;
> }
> static void operator delete(void* p) {
> cout << "Deleting TraceHeap object at address "
> << p << endl;
> ::operator delete(p);
> }
> TraceHeap(int i) //*******NOTE B
> : i(i)
> {
> ;
> }
> int getVal() const { return i; }
> };
>
>
>
> int main() {
> auto_ptr<TraceHeap> pMyObject(new TraceHeap(5));
> cout << pMyObject->getVal() << endl; // Prints 5
> }
> //------------------------------------------------------------------
>
> My question is :
>
> In My code: which code will be called first? The *NOTE A* or *NOTE B* ?
> And Why?

The 'operator new' function is the class-wide allocation function.
Before any object of that class can be constructed in free store, the
memory has to be allocated. That's why the allocation happens before
the construction.

> I'm debugging through this code and found that *NOTE A* will called
> first. Can someone explained it?

I think I just did.

> When I trace into the *new* function, the *siz* value is 4. I don't know
> why it will be 4?

The object of type TraceHeap that you're creating has a single data
member, 'int i', and no virtual functions or base classes. It's
reasonable to conclude that nothing contributes to the size of the
object except the data members. On your platform 'int' probably has the
size of 4 bytes... Try printing out 'sizeof(TraceHeap)' somewhere, what
do you get.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Jirí Palecek

10/3/2008 6:22:00 PM

0

On Fri, 03 Oct 2008 18:00:28 +0200, asm23 <asmwarrior@gmail.com> wrote:

> Hi, everyone, I'm studying the <<Thinking in C++>> volume Two. In
> Chapter One, the example code : Auto_ptr.cpp
> //-------------------------------------------------------
> #include <memory>
> #include <iostream>
> #include <cstddef>
> using namespace std;
>
> class TraceHeap {
> int i;
> public:
> static void* operator new(size_t siz) { //*****NOTE A
> void* p = ::operator new(siz);
> cout << "Allocating TraceHeap object on the heap "
> << "at address " << p << endl;
> return p;
> }
> static void operator delete(void* p) {
> cout << "Deleting TraceHeap object at address "
> << p << endl;
> ::operator delete(p);
> }
> TraceHeap(int i) //*******NOTE B
> : i(i)
> {
> ;
> }
> int getVal() const { return i; }
> };
>
>
>
> int main() {
> auto_ptr<TraceHeap> pMyObject(new TraceHeap(5));
> cout << pMyObject->getVal() << endl; // Prints 5
> }
> //------------------------------------------------------------------
>
> My question is :
>
> In My code: which code will be called first? The *NOTE A* or *NOTE B* ?
> And Why?
>
> I'm debugging through this code and found that *NOTE A* will called
> first. Can someone explained it?

I haven't looked up the standard, but common sense tells the constructor
cannot be called before memory allocation, as it needs to construct an
object in the memory allocated by the new operator.

> When I trace into the *new* function, the *siz* value is 4. I don't know
> why it will be 4?

That's sizeof(TraceHeap)

Regards
Jiri Palecek

asm23

10/4/2008 12:27:00 AM

0

Victor Bazarov wrote:
>
> The 'operator new' function is the class-wide allocation function.
> Before any object of that class can be constructed in free store, the
> memory has to be allocated. That's why the allocation happens before
> the construction.
>

Thanks Victor. I understand, I confused with *allocation* and
*construction*. But now, I know they are different and executing
sequence of them.

>
> I think I just did.
>
>
> The object of type TraceHeap that you're creating has a single data
> member, 'int i', and no virtual functions or base classes. It's
> reasonable to conclude that nothing contributes to the size of the
> object except the data members. On your platform 'int' probably has the
> size of 4 bytes... Try printing out 'sizeof(TraceHeap)' somewhere, what
> do you get.
>
> V

oh, Yes, the sizeof(TraceHeap) is 4. But I still have a puzzle. Why
these is a *static* before the overloaded new and delete operation?
I do know static function doesn't pass the *this* parameters. But in
this case, a static new or a normal new seems have no difference.

Thank you for help me.

James Kanze

10/4/2008 7:59:00 AM

0

On Oct 3, 6:00 pm, asm23 <asmwarr...@gmail.com> wrote:
> Hi, everyone, I'm studying the <<Thinking in C++>> volume Two.
> In Chapter One, the example code : Auto_ptr.cpp
> //-------------------------------------------------------
> #include <memory>
> #include <iostream>
> #include <cstddef>
> using namespace std;

> class TraceHeap {
> int i;
> public:
> static void* operator new(size_t siz) { //*****NOTE A
> void* p = ::operator new(siz);
> cout << "Allocating TraceHeap object on the heap "
> << "at address " << p << endl;
> return p;
> }
> static void operator delete(void* p) {
> cout << "Deleting TraceHeap object at address "
> << p << endl;
> ::operator delete(p);
> }
> TraceHeap(int i) //*******NOTE B
> : i(i)
> {
> ;
> }
> int getVal() const { return i; }
> };

> int main() {
> auto_ptr<TraceHeap> pMyObject(new TraceHeap(5));
> cout << pMyObject->getVal() << endl; // Prints 5
> }
> //------------------------------------------------------------------

> My question is :

> In My code: which code will be called first? The *NOTE A* or
> *NOTE B* ? And Why?

NOTE A, obviously. The trivial reason is because that is what
the language requires. Of course, the reason the language
requires this is that it couldn't possibly work otherwise: you
have to allocate the memory for the object before you can
construct it.

> I'm debugging through this code and found that *NOTE A* will called
> first. Can someone explained it?

Think. What would it mean if NOTE B were called before NOTE A.

> When I trace into the *new* function, the *siz* value is 4. I don't know
> why it will be 4?

Because that's the size of a TraceHeap object on your machine.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

James Kanze

10/4/2008 8:02:00 AM

0

On Oct 3, 6:17 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> The 'operator new' function is the class-wide allocation
> function. Before any object of that class can be constructed
> in free store, the memory has to be allocated. That's why the
> allocation happens before the construction.

Just a nit, but that last sentence applies to all objects, not
just those dynamically allocated. One of the particularities of
C++ is that there is NO syntax for calling a constructor without
formally allocating memory. (In the case of placement new, of
course, the "allocation" is purely formal. But you still have
to tell the compiler what memory it should use.)

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Bo Persson

10/4/2008 8:06:00 AM

0

asm23 wrote:
>
> oh, Yes, the sizeof(TraceHeap) is 4. But I still have a puzzle. Why
> these is a *static* before the overloaded new and delete operation?
> I do know static function doesn't pass the *this* parameters. But in
> this case, a static new or a normal new seems have no difference.
>
> Thank you for help me.

You are right, it doesn't matter. The operators new and delete are
static, whether you write 'static' or not.

The author of this code perhaps believed that it is more clear if this
is stated explicitly. Maybe it is not? :-)


Bo Persson


asm23

10/4/2008 3:28:00 PM

0

Bo Persson wrote:
> asm23 wrote:
>> oh, Yes, the sizeof(TraceHeap) is 4. But I still have a puzzle. Why
>> these is a *static* before the overloaded new and delete operation?
>> I do know static function doesn't pass the *this* parameters. But in
>> this case, a static new or a normal new seems have no difference.
>>
>> Thank you for help me.
>
> You are right, it doesn't matter. The operators new and delete are
> static, whether you write 'static' or not.
>
> The author of this code perhaps believed that it is more clear if this
> is stated explicitly. Maybe it is not? :-)
>
>
> Bo Persson
>
>
Thanks Bo, I see.

asm23

10/4/2008 3:37:00 PM

0

James Kanze wrote:
> NOTE A, obviously. The trivial reason is because that is what
> the language requires. Of course, the reason the language
> requires this is that it couldn't possibly work otherwise: you
> have to allocate the memory for the object before you can
> construct it.
>
>> I'm debugging through this code and found that *NOTE A* will called
>> first. Can someone explained it?
>
> Think. What would it mean if NOTE B were called before NOTE A.
>
>> When I trace into the *new* function, the *siz* value is 4. I don't know
>> why it will be 4?
>
> Because that's the size of a TraceHeap object on your machine.
>
> --
> James Kanze (GABI Software) email:james.kanze@gmail.com
> Conseils en informatique orientée objet/
> Beratung in objektorientierter Datenverarbeitung
> 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Thanks, James.
Now, I understand the important concept of " allocating before
construction ".

I think the author overload the operator new of TraceHeap is just to
show some message.

static void* operator new(size_t siz) { //*****NOTE A
void* p = ::operator new(siz);
cout << "Allocating TraceHeap object on the heap "
<< "at address " << p << endl;
return p;
}

the parameter *size_t siz* will be filled at compiling time. So, the
compiler will set the siz value to sizeof(TraceHeap).

Is my understanding right? Thanks.

Hendrik Schober

10/5/2008 7:39:00 PM

0

James Kanze wrote:
> On Oct 3, 6:17 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
>> The 'operator new' function is the class-wide allocation
>> function. Before any object of that class can be constructed
>> in free store, the memory has to be allocated. That's why the
>> allocation happens before the construction.
>
> Just a nit, but that last sentence applies to all objects, not
> just those dynamically allocated. One of the particularities of
> C++ is that there is NO syntax for calling a constructor without
> formally allocating memory. [...]

I don't doubt that you're right, but I'd like to know
what this
std::string("huh?")
is if it's not the explicit invocation of a constructor.

Schobi

Victor Bazarov

10/5/2008 10:16:00 PM

0

Hendrik Schober wrote:
> James Kanze wrote:
>> On Oct 3, 6:17 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
>>> The 'operator new' function is the class-wide allocation
>>> function. Before any object of that class can be constructed
>>> in free store, the memory has to be allocated. That's why the
>>> allocation happens before the construction.
>>
>> Just a nit, but that last sentence applies to all objects, not
>> just those dynamically allocated. One of the particularities of
>> C++ is that there is NO syntax for calling a constructor without
>> formally allocating memory. [...]
>
> I don't doubt that you're right, but I'd like to know
> what this
> std::string("huh?")
> is if it's not the explicit invocation of a constructor.

It is a creation of a temporary object, which of course *causes* a call
to the constructor (and later a destructor at the end of the object's
lifetime, which is impossible for you to prevent, BTW).

You *may* call it an "explicit invocation", and start beating that dead
horse again, but let me just make a note here: if it's an invocation,
it's not explicit. The constructor is *invoked* or *called* by the
execution environment when you *create an object*. The language of the
Standard is such that there cannot be *direct* call to the constructor
simply because constructors do not have names and cannot be found during
lookup.

No, back to the subject at hand. James said you cannot call (or invoke,
if you will) a constructor without allocating memory first, and not that
you can't call a constructor (or cause its invocation). When you do

std::string("bleh")

the system will *still* allocate memory for you first, and then invoke
the constructor to construct the object in that memory. You do not call
the constructor. You do not allocate memory. The syntax is for object
creation, and you give the system the responsibility for the low-level
stuff.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask