[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
On Mon, Oct 20, 2003 at 10:27:29PM -0400, Kevin Brosius wrote:
<snip />
> > I have always understood that the "this" pointer accessible in non-static
> > member functions of C++ objects (classes, structs or unions) is actually
> > an implicit argument added by the compiler.
<snip />
> >
>
> You are closer to correct, I think. I'm less than impressed with
> Stroustrup's coverage of implementation details like this, though. (See
> comments later.)
>
> >
> > My instructor seems to think otherwise. Here is the explination I
> > was given:
> >
> > All classes, structs and unions contain a *this pointer that
> > references itself. The object also contains pointers to the object
> > member functions, therefore when calling a member function in an
> > object the member function has access to the *this pointer.
> >
>
> I don't see any evidence that objects contain a copy of *this
I don't either, see the end for a simple proof.
> themselves, from Stroustrup. And really, there's no need. The storage
> location for the object is generally equivalent to *this. Think of it
Exactly, which is why "calling" the member function with the first
argument as a pointer to the calling object makes perfect sense.
> this way, the object address equals *this, for non-static objects. The
> compiler/linker tracks storage location, and resolves it at link time.
> It's not needed to be a member of the object.
>
<snip />
> > This makes no sense to me. First there is the question of how does the
> > function (which is instantiated only once, which I know to be true) know
> > which object is "calling" it? Is there a way for a function (any
> > function) to "know" what object it was called from other than providing
> > it with a pointer to that object?
> >
> > Furthur, a simple sizeof() test shows that this (the instructor's idea
> > of how an object is created and stored) can't be true unless sizeof()
> > doesn't return the true size of an object (which would be VERY bad
> > especially if you tried to combine a malloc() call to get the required
> > memory instead of new).
> >
> > By using the simple Foo class above, with only one private data member
> > (x), and one public member function (void setx(int)), I see that the
> > sizeof(Foo) is 4 (which happens to be sizeof(int)). Is my instructor
> > full of it or am I missing something here?
> >
> > If I have it wrong, please someone point me to some documentation that
> > shows me exactly how a class' member functions (non-static) "know" which
> > object has called them and where they get *this.
>
>
> Well, you might want to think of it from a usage standpoint. I think
> you'll find that the functions don't always need a *this pointer. It
> depends on the implementation. For example:
>
> class Foo {
>
> public:
> void print(void) { printf("Hello World"); };
> };
>
> If I call an instance of the above, what happens?
>
> Foo foo;
> foo.print();
>
> I'd bet most recent compilers don't pass *this for the above case. It's
> unneeded for the implementation.
Certainly, there's no references to any members here and therefore the
compiler can treat this as a static function. But is this true? Think
of callbacks, try using the above print() as a callback. At least for
g++, it still doesn't allow it which makes me believe that the implicit
*this is still passed to the function.
>
> How about:
>
> class Foo {
> private:
> int x;
>
>
> public:
> void setx(int a) { x = a; };
> };
>
> calling:
>
> Foo foo;
> foo.setx(5);
>
> Now, in this case I'd bet you are correct, meaning this case behaves
> like "setx(*this, 5)". But here's where I think your instructor is
> wrong. There's no need for the object to contain the *this pointer.
> The compiler can determine the object referred to by the usage. The
> 'foo.' refers to the object, tracking the *this value, so to speak. If
> it's needed for the function call, to access object members, then the
> compiler passes it on call. If not, we don't need to pass the *this
> value to the function call.
>
> Stroustrup says
> "In a nonstatic member function, the keyword 'this' is a pointer to
> the object for which the function was invoked. In a non-const member
> function of class X, the type of 'this' is X*." [2]
> It doesn't say a whole lot more about how that is implemented, but I
> think it fits the description I gave above, and what you thought was
> correct. I suppose it is possible that a larger overhead compiler might
> implement what your instructor suggests. Possibly he is familiar with
> some early implementation that used table lookup heavily.
That could be, he did explain the "proper" way a compiler "should"
store an array and his explination used table lookup heavily.
>
> --
> Kevin
>
> [1] The C++ Programming Language, Special Edition (3rd. ed., Jan 2003).
> Bjarne Stroustrup. p.231.
Thanks for the reference, I'll get that book. The author of the book
I have also seems to think that the *this pointer is part of the object.
I have done some simple verification (thanks to Jeff Abrahamson for this
test) and see that the *this pointer is not a part of the object.
class foo {
public:
void print();
};
foo f;
fwrite(&f, sizeof(f), 1, stdout);
fprintf(stderr, "&f: 0x%x\n", &f);
Pipe to od -t x4 and you see nothing in the object containing
the address to f:
./test | od -t x4
&f: 0xbffff987
0000000 000000bf
0000001
--
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d-(+) s:>++:++ a->-- C++++$ UL++++$ P++++$ L++++$ E--- W++(+++)$
N(-) o-- K- w--- !O? M- V-- PS++(+++) PE-- Y++ PGP t+(++) 5 X R tv(--)
b+>+++ DI+++ D+(++) G e+>++>+++>++++ h-- r--->+++ y-->+++
------END GEEK CODE BLOCK------
___________________________________________________________________________
Philadelphia Linux Users Group -- http://www.phillylinux.org
Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce
General Discussion -- http://lists.phillylinux.org/mailman/listinfo/plug