|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
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. |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Luis Angel Fernandez Fernandez wrote:
> 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 -- Please remove capital 'A's when replying by e-mail I do not respond to top-posted replies, please don't ask |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Jan 15, 10:59 am, Luis Angel Fernandez Fernandez
<laff...@gmail.com> wrote: > 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? > > Thanks in advance. |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On 15 Jan, 15:59, Luis Angel Fernandez Fernandez <laff...@gmail.com>
wrote: > 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/com...427ed638?hl=en |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
El Tue, 15 Jan 2008 08:15:40 -0800, tragomaskhalos escribió:
Hi, again. Thank you all for your anwsers. >> 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; } That's what we thought, but when we saw it working (or doing something it seemed right) we were surprised. >> Â And... why ((A*)NULL)->foo() works too? >> > > This came up recently, see: > http://groups.google.co.uk/group/com...thread/thread/ > a807522e71a60c8e/f4afa72f427ed638?hl=en Thank you. I was searching something about that, but I couldn't find anything. Bye. -- Ubuntu 7.10 (gutsy) (kernel 2.6.22-14-generic i686) GNOME 2.20.1 Intel(R) Core(TM)2 Quad CPU (2260.245 MHz) up 33 min, 2 users HT: ZanzabornÃn (1457021) X.1762 # http://muxin.no-ip.org/ SK: C.D. Arrancatapinos (18088) IV.57 # Jabber: laffdez@gmail.com |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
On Jan 15, 1:40 pm, "Luis Angel Fdez. Fdez." <laff...@gmail.com>
wrote: > El Tue, 15 Jan 2008 08:15:40 -0800, tragomaskhalos escribió: > > Hi, again. > > Thank you all for your anwsers. > > >> 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; } > > 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. > > >> And... why ((A*)NULL)->foo() works too? > > > This came up recently, see: > >http://groups.google.co.uk/group/com...thread/thread/ > > a807522e71a60c8e/f4afa72f427ed638?hl=en > > Thank you. I was searching something about that, but I couldn't find > anything. > > Bye. > > -- > Ubuntu 7.10 (gutsy) (kernel 2.6.22-14-generic i686) GNOME 2.20.1 > Intel(R) Core(TM)2 Quad CPU (2260.245 MHz) up 33 min, 2 users > HT: Zanzabornín (1457021) X.1762 #http://muxin.no-ip.org/ > SK: C.D. Arrancatapinos (18088) IV.57 # Jabber: laff...@gmail.com |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
Salt_Peter <pj_hern@yahoo.com> writes:
> On Jan 15, 10:59 am, Luis Angel Fernandez Fernandez > <laff...@gmail.com> wrote: > [...] >> And... why ((A*)NULL)->foo() works too? > > 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 |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
Luis Angel Fernandez Fernandez wrote:
> 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 ); > Thanks in advance. -- Jim Langston tazmaster@rocketmail.com |
|
|
|
#9 |
|
Messages: n/a
Hébergeur: |
On Jan 15, 4:36 pm, Pascal Bourguignon <p...@informatimago.com> wrote:
> Salt_Peter <pj_h...@yahoo.com> writes: > > On Jan 15, 10:59 am, Luis Angel Fernandez Fernandez > > <laff...@gmail.com> wrote: > > [...] > >> And... why ((A*)NULL)->foo() works too? > > > jump off a bridge: does that work too? > > There are small bridges, and there are high bridges ;-) feel free to test the difference. > > > 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 |
|
![]() |
| Outils de la discussion | |
|
|