Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
February 10, 2007 &this pointer | ||||
---|---|---|---|---|
| ||||
Hi, I'm a beginner with D, I've got some basis with C/C++ but I mainly program with PHP. Ad far as I'm concerned, D is a very interesting language, hence I started to develop a personal project in D to get a clear idea of its features ; nonetheless, during my research, I've noticed a behavior I considered very weird about the 'this' reference. According to what I understood from the documentation, it is a reference to the object itself, so coherently, &this should return the memory address of the object itself. It that is correct, could one explain that to me (compiled with DMD 1.0) : --- import std.stdio; import std.string; class Test { this() { writefln("in this() itself - &this : ", &this); foo("called from this(), first shot"); foo("called from this(), second shot"); } void foo(char[] location) { writefln(location, " - foo() - &this : ", &this); bar(location); } void bar(char[] location) { writefln(location, " - bar() - &this : ", &this); } } int main() { auto test = new Test(); test.foo("called from main(), first shot"); test.foo("called from main(), second shot"); return 0; } --- $ ./test in this() itself - &this : BFAE4394 called from this(), first shot - foo() - &this : BFAE4370 called from this(), first shot - bar() - &this : BFAE4344 called from this(), second shot - foo() - &this : BFAE4370 called from this(), second shot - bar() - &this : BFAE4344 called from main(), first shot - foo() - &this : BFAE438C called from main(), first shot - bar() - &this : BFAE4360 called from main(), second shot - foo() - &this : BFAE438C called from main(), second shot - bar() - &this : BFAE4360 --- In accordance with the output, the object location in memory endlessly changes ?! I admit to be a little startled... e-t172 |
February 10, 2007 Re: &this pointer | ||||
---|---|---|---|---|
| ||||
Posted in reply to e-t172 | By reference it means that 'this' already *is* a pointer. You don't need to take it's address. If you do you're just getting the address of the pointer not the address of the object. Try something like writefln("%x",cast(void*)this); if you really want to see the address of the object. --bb e-t172 wrote: > Hi, > > I'm a beginner with D, I've got some basis with C/C++ but I mainly program with PHP. Ad far as I'm concerned, D is a very interesting language, hence I started to develop a personal project in D to get a clear idea of its features ; nonetheless, during my research, I've noticed a behavior I considered very weird about the 'this' reference. According to what I understood from the documentation, it is a reference to the object itself, so coherently, &this should return the memory address of the object itself. > > It that is correct, could one explain that to me (compiled with DMD 1.0) : > > --- > > import std.stdio; > import std.string; > > class Test > { > this() > { > writefln("in this() itself - &this : ", &this); > > foo("called from this(), first shot"); > foo("called from this(), second shot"); > } > > void foo(char[] location) > { > writefln(location, " - foo() - &this : ", &this); > > bar(location); > } > > void bar(char[] location) > { > writefln(location, " - bar() - &this : ", &this); > } > } > > int main() > { > auto test = new Test(); > > test.foo("called from main(), first shot"); > test.foo("called from main(), second shot"); > > return 0; > } > > --- > > $ ./test > in this() itself - &this : BFAE4394 > called from this(), first shot - foo() - &this : BFAE4370 > called from this(), first shot - bar() - &this : BFAE4344 > called from this(), second shot - foo() - &this : BFAE4370 > called from this(), second shot - bar() - &this : BFAE4344 > called from main(), first shot - foo() - &this : BFAE438C > called from main(), first shot - bar() - &this : BFAE4360 > called from main(), second shot - foo() - &this : BFAE438C > called from main(), second shot - bar() - &this : BFAE4360 > > --- > > In accordance with the output, the object location in memory endlessly changes ?! I admit to be a little startled... > > e-t172 |
February 10, 2007 Re: &this pointer | ||||
---|---|---|---|---|
| ||||
Posted in reply to e-t172 | e-t172 wrote: > I've noticed a behavior I considered very weird about the 'this' reference. According to what I understood from the documentation, it is a reference to the object itself, Correct. > so coherently, &this should return the memory address of the object itself. Wrong. A reference in D is different from a reference in C++. If you take the address of a reference in D, you do not get the address of the object referenced, but the address of the reference itself. Think of a D reference as a pointer to the body of the class, with small differences. For one, casting between references works differently. For another, pointer arithmetic doesn't work on references. But operators like (unary) & work the same: in this case, it returns a pointer to the memory storing the address being referred to. To get the address of the object from a reference you can cast it to void*. So in your case, replace "&this" with "cast(void*)this" and you will see the same address everywhere. |
February 10, 2007 Re: &this pointer | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frits van Bommel | Frits van Bommel a écrit :
> A reference in D is different from a reference in C++. If you take the address of a reference in D, you do not get the address of the object referenced, but the address of the reference itself.
> Think of a D reference as a pointer to the body of the class, with small differences. For one, casting between references works differently. For another, pointer arithmetic doesn't work on references. But operators like (unary) & work the same: in this case, it returns a pointer to the memory storing the address being referred to.
>
> To get the address of the object from a reference you can cast it to void*. So in your case, replace "&this" with "cast(void*)this" and you will see the same address everywhere.
Thank you very much :)
e-t172
|
February 10, 2007 Re: &this pointer | ||||
---|---|---|---|---|
| ||||
Posted in reply to e-t172 | The phrase "&this" returns the address of the hidden 'this' parameter passed to the member functions. In other words, you are seeing the address of a parameter on the stack.
If you are trying to get the address of the class instance, the phrase
"cast(void *)this"
seems to work, but I'm sure there are other techniques too.
--
Derek Parnell
Melbourne, Australia
"Justice for David Hicks!"
skype: derek.j.parnell
|
February 11, 2007 Re: &this pointer | ||||
---|---|---|---|---|
| ||||
Posted in reply to e-t172 | The following does not work : import std.stdio; class Test { this() { void* ptr = cast(void*) this; (*(cast(Test*) ptr)).foo(); } void foo() { writefln("OK"); } } int main() { auto test = new Test(); return 0; } Result : segmentation fault Could one explain why ? |
February 11, 2007 Re: &this pointer | ||||
---|---|---|---|---|
| ||||
Posted in reply to e-t172 | e-t172 wrote:
> The following does not work :
>
> import std.stdio;
>
> class Test
> {
> this()
> {
> void* ptr = cast(void*) this;
>
> (*(cast(Test*) ptr)).foo();
> }
>
> void foo()
> {
> writefln("OK");
> }
> }
>
> int main()
> {
> auto test = new Test();
>
> return 0;
> }
>
> Result : segmentation fault
>
> Could one explain why ?
"this" is of type "Test". Therefore to recover it from a void*, do simply:
(cast(Test)ptr).foo();
Brian Byrne
|
February 11, 2007 Re: &this pointer | ||||
---|---|---|---|---|
| ||||
Posted in reply to e-t172 | On Sun, 11 Feb 2007 21:14:26 +0100, e-t172 wrote: > The following does not work : > > import std.stdio; > > class Test > { > this() > { > void* ptr = cast(void*) this; > > (*(cast(Test*) ptr)).foo(); > } > > void foo() > { > writefln("OK"); > } > } > > int main() > { > auto test = new Test(); > > return 0; > } > > Result : segmentation fault > > Could one explain why ? You need "(cast(Test) ptr).foo();" instead. This is because 'void* ptr' contains the address of the object, and when calling object members, you need to use a /reference/ to the object and not the object itself. Casting 'ptr' to 'Test*' just tells the compiler to assume that 'ptr' points to a Test object and then using the '*' operator returns the object and not a reference to the object. If, however you had cast 'ptr' to just a 'Test', this tells the compiler to assume that 'ptr' contains a reference to the object and so it can then find the member to invoke. -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell |
Copyright © 1999-2021 by the D Language Foundation