I have this method:
bool CDemoPickerDlg::IsStudentTalk(CString strAssignment)
{
bool bStudentTalk = false;
CString strTalkMain, strTalkClass;
if (theApp.UseTranslationINI())
{
strTalkMain = theApp.GetSMMethod(_T("IDS_STR_HISTORY_TALK_MAIN"));
strTalkClass = theApp.GetSMMethod(_T("IDS_STR_HISTORY_TALK_AUX"));
}
else
{
strTalkMain.LoadString(IDS_STR_HISTORY_TALK_MAIN);
strTalkClass.LoadString(IDS_STR_HISTORY_TALK_AUX);
}
int iTalkMainLen = strTalkMain.GetLength();
int iTalkClassLen = strTalkClass.GetLength();
if (strAssignment.Left(iTalkMainLen) == strTalkMain ||
strAssignment.Left(iTalkClassLen) == strTalkClass)
{
bStudentTalk = true;
}
return bStudentTalk;
}
It is called multiple times. Without added "member variables" to the class to cache values is there any other way to create the values for the two CString and int values just the once? As they will not change for the duration of the program.
The method above is static. I know about assigning a value to a static variable but I understand that can only be done once at the time of declaration. Have I miss-understood that?
You can use a static constant (or variable, but why make it variable if it isn't supposed to be changed?) at function scope:
static CString const someImmutableText = <some initializer>;
The placeholder <some initializer> above can be a literal, a function call or any other expression that you can initialize a CString from. The static makes sure the object is only created once and subsequently only initialized once, too.
#Ulrich's answer will of course work fine, but if <some initializer> is non-trivial there is a hidden downside - as of C++11, the compiler is required to generate a threadsafe initialiser.
This has minimal runtime overhead but it does generate quite a lot of code, see at Godbolt, and if you have a lot of these then this can add up.
If there are no multi-threading issues (which generally there aren't, especially in initialisation code), then there is a simple alternative which will eliminate this code. In fact, it's so simple that it's barely worth posting at all, but I'll do it here anyway for completeness. It's just this; please excuse the anglicisms:
static bool initialised;
static Foo *initialise_me;
static Bar *initialise_me_too;
...
if (!initialised)
{
initialise_me = new Foo (...);
initialise_me_too = new Bar (...);
...
initialised = true;
}
...
Note that the variables to be initialised are declared as raw pointers here and allocated with new. This is done for a reason - the one thing you most definitely don't want is to call constructors at the point where you declare these variables, else you'll be right back where you started. There are no object lifetime issues because the variables remain in existence for the entire duration of the program, so it's all good.
And, in fact, you don't actually need that bool at all - just test (say) initialise_me against nullptr.
Related
I have a function which processes data that comes as a sequence. Because of this, I need to know the value of certain variables from the last function call during the current function call.
My current approach to doing this is to use static variables. My function goes something like this:
bool processData(Object message){
static int lastVar1 = -1;
int curVar1 = message.var1;
if (curVar1 > lastVar1){
// Do something
}
lastVar1 = curVar1;
}
This is just a small sample of the code; in reality I have 10+ static variables tracking different things. My gut tells me using so many static variables probably isn't a good idea, though I have nothing to back that feeling up.
My question: Is there a better way to do this?
An alternative I've been looking into is using an object whose fields are lastVar1, lastVar2, etc. However, I'm not sure if keeping an object in memory would be more efficient than using static variables.
Your question has a taste of being purely about style and opinions, though there are aspects that are not a matter of opinion: multithreading and testing.
Consider this:
bool foo(int x) {
static last_val = -1;
bool result = (x == last_val);
last_val = x;
return result;
}
You can call this function concurrently from multiple threads but it wont do the expected. Moreover you can only test the function by asserting that it does the right thing:
foo(1);
assert( foo(1) ); // silenty assumes that the last call did the right thing
To setup the preconditions for the test (first line) you already have to assume that foo(1) does the right thing, which somehow defeats the purpose of testing that call in the second line.
If the methods need the current object and the previous object, simply pass both:
bool processData(const Object& message,const Object& previous_message){
if (message.var1 > previous_message.var1){
// Do something
return true;
}
return false;
}
Of course this just shifts the issue of keeping track of the previous message to the caller, though thats straight-forward and requires not messing around with statics:
Object message, old_message;
while ( get_more( message )) {
processData(message, old_message);
old_message = message;
}
Currently, I've created a simple error handling system to check whether a pointer is valid by checking for nullptr like so:
inline void ErrReport(const char8* fileOfError, int32 lineNumberOfError, const Blz::string c_errMessage)
{
ErrorContext::LogContext();
LOG(" ERROR: %s\n", c_errMessage.c_str());
LOG(" In %s: %i\n\n", fileOfError, lineNumberOfError);
exit(0);
}
#if(_DEBUG)
#define ERRASSERT(test, msg) do {if (!(test)) Blz::Err::ErrReport(__FILE__, __LINE__, msg);} while (0)
#endif
I can then call ERRASSERT in my code like so:
unsgined char* imageData = LoadImage("PathToImage");
ERRASSERT(imageData, "Image did not load properly");
Right now, in order to do something similar with non-pointer objects I have a Check() function to see if an object has been initialized or not:
template<typename T> inline bool Check(boost::outcome::expected<T>& obj)
{
if (obj)
return true;
else
return false;
}
With this code, if I understand how to use outcome::expected correctly, I would then just call the above function within my ERRASSERT and everything should work similiarly
boost::outcome::expected<ObjectType> obj = functionReturnsObj();
ERRASSERT(Check(obj), "Object not initialized!);
My question:
Is there a better way to check if an object is initialized without having to wrap everything in boost::outcome::expected? Are there even many scenarios where an object wouldn't be initialized given C++ automatically initializes objects upon creation? Should I even be worried about this?
Is there a better way to check if an object is initialized
Don't.
Are there even many scenarios where an object wouldn't be initialized given C++ automatically initializes objects upon creation?
Yes, and it doesn't (always).
But that's the programmer's responsibility (and you can usually rely on compiler warnings to catch silly mistakes).
Should I even be worried about this?
No.
I just want to elaborate a bit on Should I even be worried about this? in addition to #BoundaryImposition's answer.
An uninitialized C++ object may cause you issues in certain cases. If you have Foo and create an instance f as below, then f.a and f.b are not initialized and you should not assume they are 0.
struct Foo { int a; int b; };
Foo f;
I wonder, is the marked line in the below code correct. Because in this line the result of the function is assigned to the static variable prevRecCallResult (I'll call it "plain assignment"), which is changed inside this function (I'll call it "inside assignment").
Is it guaranteed, that the "inside assignment" is done, when the "plain assignment" executes?
int f(int _n)
{
if (_n >= 1)
{
static int prevRecCallResult;
prevRecCallResult = f(_n - 1); //<-- Is this line Ok?
return prevRecCallResult + 1;
}
else
return _n;
}
I know, the standard says, that a sequence point occurs:
At a function return, after the return value is copied into the
calling context.
, but I'm not sure, this is the answer to my question.
Update:
Considering replies I've received, I should clarify my question:
It's essence is: Is it true, that the prevRecCallResult is not in use by the assignment expression (in marked line) (i.e. is not occupied by it) until f(_n - 1) is finished? (And thus, until this moment, prevRecCallResult is absolutely free for any assignments inside f(_n - 1)?)
static int prevRecCallResult;
prevRecCallResult = f(_n - 1); //<-- Is this line Ok?
Your code is perfectly OK. But just wanted to make you remember that static int prevRecCallResult; executes only once. But prevRecCallResult = f(_n - 1); is assigned after each function call. Once function return prevRecCallResult's at time function's return value will be used in rest of the function.
One more thing, static variable will not die, after you return from function. So prevRecCallResult will not die across function calls.
As I remember all static variables as well as all global variables in C and C++ are assigned automatically to default value for their types - in this particular example default value for 'static int prevRecCallResult' will be 0. So your fears are unfounded (you can easily check this with debugger).
At the same time I cannot understand why you use static variable in this code... is it just simplified code for question or is it real code where you trying to economize memory on automatic variable of recursive function?
In the C language, in order to initialize a static local variable to a value unknown during compilation, I would normally do something like this (for example):
void func()
{
static int var = INVALID_VALUE;
if (var == INVALID_VALUE)
var = some_other_func();
...
}
In the C++ language, I can simply do:
void func()
{
static int i = some_other_func();
...
}
The only way (that I can think of) for a C++ compiler to resolve it properly, is by replacing this code with a mechanism similar to the C example above.
But how would the compiler determine a "proper" invalid value? Or is there another way which I haven't taken into consideration?
Thanks
Clarification:
INVALID_VALUE is a value which function some_other_func never returns.
It is used in order to ensure that this function is never invoked more than once.
The compiler will not generate code to do it based on its value but on a thread safe flag that ensure that the code is only executed once.
Something like that:
void func()
{
static int i;
static bool i_initialized;
if (!i_initialized) {
i = some_other_func();
i_initialized = true;
}
}
Except that generally it is not a bool but a thread safe way of testing it.
According to code seen by disassembling and debugging the g++ compiled code, there is a hidden variable that is initialized to 0 and when the initialization is run it is set to 1.
So the next time the initialization code isn't executed.
I have some small helper functions needed throughout the code.
To work, they need to be initialized with some data once.
Where should I store the init data?
I've come up with two methods:
I create static variables in the scope of the helper.cpp file which I set with a dedicated setter function and then use in my helper function.
static int _initData = 0;
void initHelpMe(int initData)
{
_initData = initData;
}
void helpMe()
{
doSomethingWith(_initData);
}
Or I use a static function variable inside the original helper function and a default parameter to it.
void helpMe(int initData = 0)
{
static int _initData = 0;
if (initData != 0)
_initData = initData;
doSomethingWith(_initData);
}
(Lets asume that 0 is outside of the valid data range of initData and that I've not shown additional code to ensure an error is raised when the function is called for the first time without initiating it first.)
What are the advantages / disadvantages of those two methods and is there an even better way of doing it?
I of course like the second method, because it keeps all the functionality in one place. But I already know it is not thread-safe (which is not an issue a.t.m.).
And, to make this more interesting, albeit being C++ this is not to be used in object-oriented but in procedural code. So please no answers proposing objects or classes. Just imagine it to be C with the syntax of C++.
I was going to suggest that you wrap your data into an object, until I realized that you are asking for a C solution with a C++ tag...
Both of your solutions have their benefits.
The second one is the one I'd prefer, assuming we just go by "what it looks like/maintainability". However, there is a drawback if helpMe is called MANY times with initData == 0, because of the extra if, which isn't present in the first case. This may or may not be an issue if doSomethingWith() is long enough a function and/or the compiler has the ability to inline helpMe (and initData is constant).
And of course, something in the code will have to call initHelpMe too, so it may turn out to be the same anyway.
In summary: Prefer the second one, based on isolation/encapsulation.
I clearly prefer the second! Global static data in different compilation units are initialized in unspecified order (In one unit in order, though). Local static data of a function is initialized at first call.
Example:
If you have two translation units A and B. The unit A calls during initialization the function helpMe of unit B. Assume the order of initialization is A, B.
The first solution will set the zero initialized _initData to some initData. After that the initialization of unit B resets _initData back to zero and may produce a memory leak or other harm.
There is a third solution:
void helpMe(int initData = 0)
{
static std::once_flag once;
static int _initData = 0;
std::call_once(once, [&] {
_initData = initData;
}
doSomethingWith(_initData);
}
I feel strongly both ways.
Prefer option 2 for the isolation, but option 1 lends itself to porting to a C++ class. I've coded both ways. It comes down to the SW architecture.
Let me offer another point.
Both options down side: You have not limited initialization to one occurrence. "need to be initialized with some data once". It appears OP's conditions insure a proper initialization of initHelpMe(123) or HelpMe(123) followed by helpMe(), but do not prevent/detect a secondary initialization.
Should a secondary need to be prevented/detected, some additional code could be used.
// Initialization
if (_initData != 0) {
; // Handle error
}
_initData = initData;
Another paradigm I've used follows. It may not be realizable in you code as it does not pass initData as a parameter but magically can get it.
void helpMe(void) {
static int Initialized = 0;
if (!Initialized) {
Initialized = 1;
_initData = initData();
}
doSomethingWith(_initData);
}