Cool Javelin wrote: ↑Wed Oct 18, 2023 8:41 pm
I tend to worry about every byte of memory and unnecessary clock cycle.
I hear you
Re: memory - It may even be beneficial to have things live on the stack
temporarily instead of permanently in statically allocated RAM...
I'd like to discuss some of the answers,
1) you say to have a "clean, internally consistent..." but when the compiler creates space on the stack, doesn't it leave whatever garbage is in memory there? Does calling the instantiating actually initialize the RAM?
Yes, in C++ a class' constructor is always executed when an instance is created, either explicitly (MyClass inst {99,100,true};) or implicitly by the compiler (MyClass inst; is the same as MyClass inst { /* nothing */ };). The constructor (together with the compiler) takes care of initializing the instance's memory.
2) I do see the advantages to limiting the scope. I spend a lot of time deciding if a variable should be local or global.
In C++ there's the additional aspect of instances being implicitly destroyed via their destructor when their scope is exited. "RAII" is the relevant pattern/acronym. This way, the
compiler makes sure the instance is properly cleaned up and resources released.
Think
Code: Select all
int func() {
MyClass inst {true,255};
if(inst.doSomehing() == false) {
return -1;
}
if(noonAlready) {
if (user == nullptr) {
throw UserUnavailabeException {};
} else {
inst.restUser(user);
}
}
return inst.getResult();
}
The destructor will always be executed when func() is exited. This is especially relevant when an instance internally holds resources, whether that's memory allocated from the heap or a specific network connection.
3) Again, I see the need to do if the code is reentrant. I try very hard to not use reentrant code for fear of overrunning the stack so it never occurs to me.
Think about a function potentially being called concurrently from more than one task.
In this case, where it may be impossible to know beforehand how many "instances" of the function may actually be running concurrently at some point, the most reasonable thing may be use the calling task's stack, so that memory is only used if&when any given task actually calls the function.