Open Side Menu Go to the Top

04-06-2013 , 08:37 PM
Ok, so

new Flight(); // is a pointer to a class instance

but doesn't

Flight** ptrFlight = new Flight*[100];

mean that ptrFlight is a pointer to a pointer?

so if we assign

ptrFlight=new Flight();

isn't it a pointer to an instance of an object rather than a pointer to a pointer?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **
$25m Guaranteed WPM on CoinPoker
Join the action now
Daily Rewards • Splash Pots • CoinRaces
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **
04-06-2013 , 10:26 PM
Flight **ptrFlight = new Flight(); // this doesn't work

However, what you are doing is this (I added parens to make the types clearer):

Flight **ptrFlight = new (Flight *)[100];
ptrFlight[0] = new Flight();

The difference is the way the [] operator works, and the direct answer to your question is that ptrFlight[i] returns the value of the array element at position i. In this case, since each element in the array is a (Flight *), ptrFlight[i] is a (Flight *), the same as what the new keyword returns, so the assignment is OK.

Now, let me try to explain why ptrFlight is (Flight **) rather than (Flight *). It has to do with the way arrays are created and referenced.

When you create ptrFlight, you are saying I want an array of pointers-to-Flight with space for 100 pointers. You can think of the variable that gets created from new Flight *[100] as being a "pointer to an array of Flight instances."

"Pointer to an array of X" is represented by "Pointer to pointer to X" because of the way arrays are mapped into memory. The value that ptrFlight contains is the address of the first item in the array. Since the first item in the array is a pointer to Flight (remember: you created an array of Flight pointers), that means the value of ptrFlight is the address of a pointer, which is the same as saying it's a pointer to that pointer.

Arrays in C/C++ are created such that all the items in the array are laid out sequentially in memory, and the value of the array variable itself (ptrFlight) is the address of the first item. That is:

ptrFlight == &ptrFlight[0]

also

*ptrFlight is the same as ptrFlight[0]

*(ptrFlight + (1 * sizeof(Flight *))) is the same as ptrFlight[1]

In other words, the address in memory referred to by ptrFlight[5] (that is, &ptrFlight[5]) is 5 "units" away from the beginning of the array, which is the address contained by ptrFlight itself. The "unit" being the size in bytes of a pointer to a Flight instance, which is what the sizeof() is for (Note: it may not be strictly necessary to use sizeof in this case since the compiler knows that the array is of Flight * but I included it for the sake of completeness and because I can't remember if the compiler will figure it out or not :P)

So, in general the type of the variable that is the array (ptrFlight) will add one * over the type that is contained in the array

so if you create an array of ints with new int[5], the variable you assign that to is an (int *). If you create an array of pointers to ints (new int*[5]), then the array variable is an (int **), which is the equivalent to what you have here
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-06-2013 , 10:37 PM
Thank you so much for taking the time to write that. I think I kind of get it now, hopefully it will crystalize when I sleep on it.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-06-2013 , 10:50 PM
Addendum:

If you create arrays on the stack, rather than on the heap (i.e you don't use the new keyword):

int foo[5];

foo is still of type (int *). It's still a pointer. The difference is that because of the way it's been created, it's a constant pointer. Its type is (const int *), which means that you can't ever use foo to point to anything else, only that array. Which may or may not be the reason the syntax entirely hides its "pointer-ness", since you can never use it to point at anything else, whereas you could do this with your code:

delete[] ptrFlight;
ptrFlight = new (Flight *)[50];
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-06-2013 , 10:59 PM
Quote:
Originally Posted by well named
...
(Note: it may not be strictly necessary to use sizeof in this case since the compiler knows that the array is of Flight * but I included it for the sake of completeness and because I can't remember if the compiler will figure it out or not :P)

...
It is not necessary and probably not coded that way very often. It certainly is equivalent though. Very good explanation.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-06-2013 , 11:05 PM
I figured as much but I write way more C then C++ and was probably thinking of the way I normally write malloc() calls, and it wasn't that long ago that I was talking to chips ahoy about the size of pointers in C++ being variable (my mind is still blown) so you can never be too safe!
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-06-2013 , 11:17 PM
OK so now I think I see why I can't dereference ptrFlight[2] twice. But I guess **(ptrFlight+2) would be the same as *ptrFlight[2]
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-06-2013 , 11:18 PM
That's correct.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-06-2013 , 11:28 PM
Quote:
Originally Posted by well named
I figured as much but I write way more C then C++ and was probably thinking of the way I normally write malloc() calls, and it wasn't that long ago that I was talking to chips ahoy about the size of pointers in C++ being variable (my mind is still blown) so you can never be too safe!
The bolded, no doubt about it.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-06-2013 , 11:29 PM
thinking about it some more I think using sizeof() in pointer arithmetic probably isn't equivalent and just doesn't work right, so I was wrong on that. I was thinking of malloc which takes a number of bytes, but pointer arithmetic is always in units of the specific type anyway.

There's probably some weird exception involving offsets to struct members in C that I'm thinking of too, or something, I dunno. The C code I work on involves lots of structs being passed around as void * and referencing members using offsets from metadata :P
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-06-2013 , 11:55 PM
Quote:
Originally Posted by well named
thinking about it some more I think using sizeof() in pointer arithmetic probably isn't equivalent and just doesn't work right, so I was wrong on that. I was thinking of malloc which takes a number of bytes, but pointer arithmetic is always in units of the specific type anyway.

There's probably some weird exception involving offsets to struct members in C that I'm thinking of too, or something, I dunno. The C code I work on involves lots of structs being passed around as void * and referencing members using offsets from metadata :P
It is equivalent in the sense that they will point to the same thing. Execution speed wise ymmv.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-07-2013 , 12:11 AM
(ptr + (1 * sizeof(int *)))

if sizeof returns 4 it's going to be the same as

(ptr + 4)

which would be 4 elements in, not the 1 that we were trying for

right?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-07-2013 , 01:01 AM
Quote:
Originally Posted by well named
(ptr + (1 * sizeof(int *)))

if sizeof returns 4 it's going to be the same as

(ptr + 4)

which would be 4 elements in, not the 1 that we were trying for

right?
Yes
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-07-2013 , 01:25 AM
In C, which influences C++ here, ptr + 4 is the same as ptr[4]. In terms of what it addresses.

Last edited by Neil S; 04-07-2013 at 01:30 AM.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-07-2013 , 06:14 AM
Quote:
Originally Posted by well named
Flight **ptrFlight = new Flight(); // this doesn't work

However, what you are doing is this (I added parens to make the types clearer):

Flight **ptrFlight = new (Flight *)[100];
ptrFlight[0] = new Flight();

The difference is the way the [] operator works, and the direct answer to your question is that ptrFlight[i] returns the value of the array element at position i. In this case, since each element in the array is a (Flight *), ptrFlight[i] is a (Flight *), the same as what the new keyword returns, so the assignment is OK.

Now, let me try to explain why ptrFlight is (Flight **) rather than (Flight *). It has to do with the way arrays are created and referenced.

When you create ptrFlight, you are saying I want an array of pointers-to-Flight with space for 100 pointers. You can think of the variable that gets created from new Flight *[100] as being a "pointer to an array of Flight instances."

"Pointer to an array of X" is represented by "Pointer to pointer to X" because of the way arrays are mapped into memory. The value that ptrFlight contains is the address of the first item in the array. Since the first item in the array is a pointer to Flight (remember: you created an array of Flight pointers), that means the value of ptrFlight is the address of a pointer, which is the same as saying it's a pointer to that pointer.

Arrays in C/C++ are created such that all the items in the array are laid out sequentially in memory, and the value of the array variable itself (ptrFlight) is the address of the first item. That is:

ptrFlight == &ptrFlight[0]

also

*ptrFlight is the same as ptrFlight[0]

*(ptrFlight + (1 * sizeof(Flight *))) is the same as ptrFlight[1]

In other words, the address in memory referred to by ptrFlight[5] (that is, &ptrFlight[5]) is 5 "units" away from the beginning of the array, which is the address contained by ptrFlight itself. The "unit" being the size in bytes of a pointer to a Flight instance, which is what the sizeof() is for (Note: it may not be strictly necessary to use sizeof in this case since the compiler knows that the array is of Flight * but I included it for the sake of completeness and because I can't remember if the compiler will figure it out or not :P)

So, in general the type of the variable that is the array (ptrFlight) will add one * over the type that is contained in the array

so if you create an array of ints with new int[5], the variable you assign that to is an (int *). If you create an array of pointers to ints (new int*[5]), then the array variable is an (int **), which is the equivalent to what you have here
Great explanation
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-08-2013 , 01:30 PM
Any programmers in the Boston area interested in a .50/1 NLHE home game or something? Trying to get another player or two, have 4-5 ready to go.. I miss playing cards and I'm too busy for foxwoods/vegas with any regularity at this point.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-08-2013 , 01:47 PM
Also has anyone made a moderately complicated app in angular.js? Started playing with it yesterday, having a small love affair. Backbone.js, you were fun, but no more.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-08-2013 , 02:23 PM
there are too many <name>.js thingies

everytime I get used to one someone pops up espousing the benefits of another
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-08-2013 , 02:31 PM
well angular.js is created by google, so you know it's awesome.

I wanted batman.js to be awesome, and it kind of was, but had like no help available online. I hear knockout is cool, ember is good... what else am I missing?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-08-2013 , 02:35 PM
horsewithhandsonhishead.js

Spoiler:


** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-08-2013 , 03:02 PM
Quote:
Originally Posted by Nchabazam
well angular.js is created by google, so you know it's awesome.

I wanted batman.js to be awesome, and it kind of was, but had like no help available online. I hear knockout is cool, ember is good... what else am I missing?
i've messed with a bunch of them, not in depth, but angular is the clear winner for my money. super ez to get up and running with basic stuff, very high learning curve to really understand it fully, but produces the most declarative and concise code when used correctly.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-08-2013 , 03:04 PM
Quote:
Originally Posted by well named
horsewithhandsonhishead.js
Nice
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-08-2013 , 03:50 PM
Quote:
Originally Posted by Nchabazam
well angular.js is created by google, so you know it's awesome.
Says the crowd that's never seen the 21,000 LOC Hello World Google Closure Compiler produces.

All of these frameworks and skins are great, but... Well, you know where I'm going with this.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-08-2013 , 07:56 PM
Hi, gaming_mouse, I'm still working through that article. I'm truly mystified by this section:

Quote:
I was recently watching an artist friend begin a painting, and I asked him what a particular shape on the canvas was going to be. He said that he wasn't sure yet; he was just "pushing paint around on the canvas", reacting to and getting inspired by the forms that emerged. Likewise, most musicians don't compose entire melodies in their head and then write them down; instead, they noodle around on a instrument for a while, playing with patterns and reacting to what they hear, adjusting and sculpting.

An essential aspect of a painter's canvas and a musical instrument is the immediacy with which the artist gets something there to react to. A canvas or sketchbook serves as an "external imagination", where an artist can grow an idea from birth to maturity by continuously reacting to what's in front of him.

Programmers, by contrast, have traditionally worked in their heads, first imagining the details of a program, then laboriously coding them.
Really? I don't think like this at all.

I guess now that I think of it, I was always mystified by people who don't think like this. I guess the real-world example would be my experience in doing remodeling. You can always tell right away the "good" from the "bad" very quickly. Mind that this is coming from a world where you "measure twice and cut once," so there really is no room for error. Every mistake adds up and those mistakes add up quickly.

The bad workers (thinkers if you will) looks at something and has two reactions: ****, wtf do I do? I won't discuss this one. The next level up is that they think back on what someone once told them and then they auto-pilot into the solution, or at least try to. The point is that they spend all their mental energy thinking of exactly one way to do it and then once the solution is in mind, they go ahead and do it that way. If it is a good solution or bad solution doesn't matter.

The very good ones don't think like this. Mind that they have to "eyeball" a solution. This one looks at the situation and thinks of 5 solutions within 5 seconds. Now they have these five design possibilities and they are able to quickly parse out the ones that work the best. Maybe they "stick up" (build a prototype with just enough nails to hold it together) and adjust accordingly.

When I program, I don't think like he is asserting at all. I have several ideas in my head at once and build somewhat haphazardly at first and then slowly tweek the answer until elegance (hopefully) emerges.

Maybe that is the divide I can't quite get across with this article. The article seems to suggest an utter fear of failure and being wrong, and this is a disastrous approach to anything, especially in learning. Failure is exactly how everyone learns. No one can achieve mastery until they take a few beatings.

I'm also not able to wrap my brain around why he wouldn't suggest what is, to me, the purely obvious solution to all of this. He sets up things to being while loops because for loops are a bit difficult to grok. That I'm cool with, but rather than add all that design stuff to it, why wouldn't he have the student do exactly ONE iteration instead of 20? Why wouldn't the program actually teach the student each item piecewise?

Code:
var i = 0;
while(i < 2){
    rotate(1);
}
Then:

Code:
var i = 0;
while(i < 3){
    rotate(1);
}
I know its "slow" and the student won't "feel" like they are learning, but this plan is 10x faster than hitting someone over the head with -- 140 different items and permutes to track! If it was done piecewise, the student would be able to bust out the solution on her own within 2 days and not have to think about it. At least I hope. I don't have any issues at all with the apparent divide between what I write on the page and what the code produces, but once again, that is probably a divide that I'm simply not understanding.

Quote:
Working in the head doesn't scale. The head is a hardware platform that hasn't been updated in millions of years. To enable the programmer to achieve increasingly complex feats of creativity, the environment must get the programmer out of her head, by providing an external imagination where the programmer can always be reacting to a work-in-progress.
This is pure psycho-babble bull****. It stinks of the same "justifications" used for paleo-diets, and it is just plain wrong-headed. Humans have been doing "high-scale" work for 5000+ years, and it is plainly insulting to all the history of logic, algorithms, writing, warfare, etc. we've developed over the past centuries to say our brains don't scale well. If this was really the case, then we wouldn't have electricity, tall buildings, or any growth of knowledge. To suggest that we suffer from stack overflow puts me at an utter loss of words. I guess he believes the Great Pyramids are the result of UFO landings too.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
04-08-2013 , 08:16 PM
And to continue my silly rant:

Quote:
Likewise, most musicians don't compose entire melodies in their head and then write them down; instead, they noodle around on a instrument for a while, playing with patterns and reacting to what they hear, adjusting and sculpting.
This quote alone is enough to utterly destroy his entire argument.

It was not until very recent history (<70 years ago) that composers had the equipment the hear the entirety of their symphony before it was played. In fact, for many years throughout history, it was completely faux pas for any composer to even hear their composition before the first performance!

So, why was it that the composers were able to write instrumentals for 20 instruments that far surpasses the complexity of our modern musicians who "noodle around" until a song comes up. Why is their music not only more timeless, but still inspiring our modern rock guitarists 600 years later?

Ponder that for a moment. The evidence is pretty clear that noodling doesn't create the beauty, timelessness, or the shear complexity of the musicians who wrote it all out without hearing a single note. Why do you suppose that is? Wouldn't it stand to reason that the guitarist with the midi board and infinite sounds available would be able to "noodle" out a larger and more forceful composition than Beethoven? Why didn't this happen?

I can tell it to you in one word: Theory. These composers created 3 hour compositions for 20+ instruments all in their head because they had an incredible grasp of theory. The noodler doesn't know anything beyond the basics.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **
$25m Guaranteed WPM on CoinPoker
Join the action now
Daily Rewards • Splash Pots • CoinRaces
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

      
m