Why pA->foo() works in this code?

  • Thread starter Luis Angel Fernandez Fernandez
  • Start date
L

Luis Angel Fernandez Fernandez

Hi

why this code works?

#include <iostream>

class A {
public:
void foo() {std::cout << "hi" << std::endl; };
};

void MakeA(A *pA) { pA = new A; }

int main() {
A* pA = NULL;
Make(pA);
pA->foo();
delete pA;

return 0;
}

And... why ((A*)NULL)->foo() works too?

Thanks in advance.
 
V

Victor Bazarov

Luis said:
why this code works?

#include <iostream>

class A {
public:
void foo() {std::cout << "hi" << std::endl; };
};

void MakeA(A *pA) { pA = new A; }

int main() {
A* pA = NULL;
Make(pA);
pA->foo();
delete pA;

return 0;
}

And... why ((A*)NULL)->foo() works too?

The code has undefined behaviour (UB). One of the results of UB
is the appearance of being "working". Read up on UB and don't
write code like that.

V
 
S

Salt_Peter

Hi

why this code works?

why shouldn't it?
#include <iostream>

class A {
public:
void foo() {std::cout << "hi" << std::endl; };

extra semicolon above
};

void MakeA(A *pA) { pA = new A; }

int main() {
A* pA = NULL;
Make(pA);
pA->foo();
delete pA;

return 0;

}

And... why ((A*)NULL)->foo() works too?

jump off a bridge: does that work too?
Modify type A by adding a member, then modify or access that member
with foo().
Do you still think you can jump off the bridge?
 
T

tragomaskhalos

  Hi
  why this code works?

class A {
  public:
    void foo() {std::cout << "hi" << std::endl; };
};

void MakeA(A *pA) { pA = new A; }

This just sets pA and then forgets it value: you mean
void MakeA(A*& pa) { pA = new A; }
int main() {
  A* pA = NULL;
  Make(pA);
  pA->foo();
  delete pA;

  return 0;

}

  And... why ((A*)NULL)->foo() works too?

  Thanks in advance.

This came up recently, see:
http://groups.google.co.uk/group/co...hread/a807522e71a60c8e/f4afa72f427ed638?hl=en
 
L

Luis Angel Fdez. Fdez.

El Tue, 15 Jan 2008 08:15:40 -0800, tragomaskhalos escribió:

Hi, again.

Thank you all for your anwsers.
This just sets pA and then forgets it value: you mean void MakeA(A*& pa)
{ pA = new A; }

That's what we thought, but when we saw it working (or doing something
it seemed right) we were surprised.

This came up recently, see:
http://groups.google.co.uk/group/comp.lang.c++/browse_thread/thread/
a807522e71a60c8e/f4afa72f427ed638?hl=en

Thank you. I was searching something about that, but I couldn't find
anything.

Bye.
 
S

Salt_Peter

El Tue, 15 Jan 2008 08:15:40 -0800, tragomaskhalos escribió:

Hi, again.

Thank you all for your anwsers.



That's what we thought, but when we saw it working (or doing something
it seemed right) we were surprised.

It doesn't forget its value, the pointer is passed by value. In other
words, the pointer pA in main() is indeed pointing to a valid new
allocation upon function return. Of course, there is a syntax error in
main():
Make(pA);
should be
MakeA(pA);

as far as the following is concerned, ask yourself: is a constructor
of any kind invoked? no, hence undefined behaviour.
 
P

Pascal Bourguignon

Salt_Peter said:
On Jan 15, 10:59 am, Luis Angel Fernandez Fernandez


jump off a bridge: does that work too?

There are small bridges, and there are high bridges ;-)
Modify type A by adding a member, then modify or access that member
with foo().
Do you still think you can jump off the bridge?

--
__Pascal Bourguignon__ http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
 
J

Jim Langston

Luis said:
Hi

why this code works?

#include <iostream>

class A {
public:
void foo() {std::cout << "hi" << std::endl; };
};

void MakeA(A *pA) { pA = new A; }

From your question I think you understand that pA in main is not being
changed, that the pA in this function is a temporary and that after this
function is closed there is no way to delete the newed A.
int main() {
A* pA = NULL;
Make(pA);
pA->foo();

pA points to NULL still. Now, why does pA->foo(); work? It is undefined
behavior. However. Most compilers (if not all?) would actually convert
this to a call like:
foo( pA );

There is only one copy of the function A::foo() even if you have 100
instances of A. The hidden this pointer points to the instance of the
class, in this case NULL. Your function
void foo() {std::cout << "hi" << std::endl; };
does not attempt to dereference the this pointer (it does not try to access
any variables of the class) so for this undefined behavior you are getting
output. If you want to see different behavior for the exact same call, try
changing your class to:

class A {
public:
void foo() {std::cout << "hi" << i << std::endl; };
private:
int i;
};

and running the program and you should see a memory access violation reading
some location. That's because now the function is attempting to dereference
the this pointer, << i << becoming something like << this->i << which is
NULL plus some offset.

You can not count on undefined behavior, it is undefined. Sometimes you can
explain it however, but that doesn't mean you should count on it to always
work that way on different compilers or even the same compiler.
delete pA;

return 0;
}

And... why ((A*)NULL)->foo() works too?

Same as above. It becomes in the compiler foo( NULL );
 

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

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top