Question on auto_ptr, Which function will call first?

A

asm23

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 = ::eek:perator 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;
::eek:perator 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.
 
J

Jiøí Paleèek

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 = ::eek:perator 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;
::eek:perator 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
 
A

asm23

Victor said:
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.
 
J

James Kanze

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 = ::eek:perator 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;
::eek:perator 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.
 
J

James Kanze

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.)
 
B

Bo Persson

asm23 said:
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
 
A

asm23

Bo said:
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.
 
A

asm23

James said:
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.


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


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

--
James Kanze (GABI Software) email:[email protected]
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 = ::eek:perator 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.
 
H

Hendrik Schober

James said:
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
 
A

asm23

Victor said:
Hendrik said:
James said:
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
That's a good clarification! Thanks.
 
H

Hendrik Schober

Victor said:
Hendrik said:
James said:
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).

Ah, thanks. You're right, of course, this creates an abject
which implies calls to a ctor and the dtor. I missed that.
Thanks!

Schobi
 
A

asm23

Jiøí Paleèek said:
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.


That's sizeof(TraceHeap)

Regards
Jiri Palecek
Thanks Jiri for your reply. I understand. A constructor can't run before
its memory has been allocated.
 
J

James Kanze

James said:
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.

According to the standard, it's an "Explicit type conversion
(functional notation)". Which in this particular case, actually
works well as a nomenclature: the semantics are exactly the same
as those of ``static_cast< std::string >( "huh?" )''. According
to the standard, ``std::string()'' and ``std::string( 5, '*' )''
are also "Explicit type conversion (functional notation)", which
I find a little bit more difficult to accept. You can't really
call them an "explicit invocation of a constructor", however,
since they do more; I rather like "explicit creation of a
temporary". But I'm afraid I have very little, if any,
influence on what people call things.
 
M

microcassanova

James said:
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.

According to the standard, it's an "Explicit type conversion
(functional notation)".  Which in this particular case, actually
works well as a nomenclature: the semantics are exactly the same
as those of ``static_cast< std::string >( "huh?" )''.  According
to the standard, ``std::string()'' and ``std::string( 5, '*' )''
are also "Explicit type conversion (functional notation)", which
I find a little bit more difficult to accept.  You can't really
call them an "explicit invocation of a constructor", however,
since they do more; I rather like "explicit creation of a
temporary".  But I'm afraid I have very little, if any,
influence on what people call things.

--
James Kanze (GABI Software)             email:[email protected]
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



the COnstructor TraceHeap should have been

explict TraceHeap(int i)
{
}

explict keyword this prevents data loss . All parameterised
constructor should have explicit keyword
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top