yea in brief...
every time you allocate and release dynamic memory, it costs.
every time you have a page fault, it costs.
the compiler may be smart enough at times to reduce it, but if you take it as coded, every dimension costs.
int foo; //this is a solid block of memory that is 200 * sizeof int bytes. It costs one push on the program stack.
int ** foo;
foo = new int*; //costs to allocate
for(int i = 0; i < 10; i++)
foo[i] = new int; //costs 10 times to allocate.
each row of foo (the first index) can be in a different page of memory (not likely, but it can happen if the computer is very active).
releasing it with a loop + outer release costs 11 more times.
if you need to work with pointers (sizes are unknown, total size too big for stack, or want some functionality like splitting off a row) it can all be done very efficiently, but it is a fair bit of extra work to dodge the aggravations above (eg you can allocate 200 ints one time and manually carve up the dimensions in the loop).
for solid block of memory:
foo for a solid block is just a multiplication statement and can be done at compile time.
for scattered memory, the same thing requires getting each address in turn and jumping to an offset that leads to the next one like the kids game where a gift box has a clue to the next box with a clue to... next next... and finally the real present is hidden somewhere at the end of the chain...
these are basic concepts that illustrate some of the problems. Again, you can force code around them and make the problems mostly go away, but that is piling up a lot of code and pointer heavy code is difficult to debug and modify and all correctly. The takeaway, then, is that going for deep dimensions is a high risk activity (as is just working with pointers at all; a simple textbook linked list suffers the page fault problem in spades)
For example (again) constexpr int* px = &x;
The type of p is int* const, constant pointer to int.
The object p cannot be modified to to point to another integer.
The pointed-to type is int. This type is not a constant type. Therefore x can be modified through *px.
I'm not sure where your confusion is, which makes it hard to give a decent explanation.
You could be confused about pointers specifically, about C++'s object model, or about the type system.
const does not do anything actively, to my knowledge.
- it lets the compiler shake a finger at you if you violate it, but that is just a compiler spew and not tied to the generated executable file.
- it may help the compiler and linker optimize the executable file. I am not sure how much of this is still true. Long ago, I found that this ran faster, but today's compilers, I no longer see it:
1 2 3 4 5 6 7 8 9
const = something tied to thisfor loop iteration
use constant in here was at one time faster than using variable back when.
I haven't felt compelled to do this in 15+ years.
the reason I say that is not active is that the above was a side effect (the compiler and linker made a smarter choice when gluing together machine language). An active change would be to somehow put machine language guards around the value to prevent it from being modified (probably possible but terribly impractical and never 100% hack proof). Const means it generates code that ensures the value is not changed. Since the compiler prevented you from making statements that DO that by throwing an error and refusing to proceed, there is nothing to do at the machine language level.
you can test it, stuff const on some stuff and leave it off, see if the executable changes at all at the byte level in release, fully optimized builds.