In some cases it happens for me to declare a variable without knowing its value first like:
int a;
if (c1) {
a = 1;
} else if (c2) {
a = 2;
} else if (c3) {
a = -3;
}
do_something_with(a);
Is it the standard professional practice to assign some clearly wrong value like -1000
anyway (making potential bugs more reproducible) or it is preferred not to add the code that does nothing useful as long as there are no bugs? From one side, looks reasonable to remove randomness, from the other side, magical and even "clearly wrong" numbers somehow do not look attractive.
In many cases it is possible to declare when the value is first known, or use a ternary operator, but here we would need it nested so also rather clumsy.
Declaring inside the block would move the variable out of the scope prematurely.
Or would this case justify the usage of std::optional<int> a
and assert(a)
later, making sure we have the value?
EDIT: The bugs I am talking about would occur if suddenly all 3 conditions are false that should "absolutely never happen".
Where can you not declare a variable in a C++ program? b) Within the block of a void function. In c++ there are three abs (absolute value) functions.
type variableName = value; Where type is one of C++ types (such as int ), and variableName is the name of the variable (such as x or myName). The equal sign is used to assign values to the variable.
A program can increment by 1 the value of a variable called c using the increment operator, ++, rather than the expression c=c+1 or c+=1.
Primitive Data Types. The primitive data types in c language are the inbuilt data types provided by the c language itself. Thus, all c compilers provide support for these data types.
Default Values Assigned to Primitive Data Types in Java Data Type Size Byte 1 byte Short 2 bytes Int 4 bytes Long 8 bytes 4 more rows ...
It is considered a best practice to initialize a primitive data type variable before using it in code.
Integer data type is used to declare a variable that can store numbers without a decimal. The keyword used to declare a variable of integer type is “int”. Thus, to declare integer data type following syntax should be followed: Float data type declares a variable that can store numbers containing a decimal number.
As far as I know the most popular and safest way is using inline lambda call. Note that the if
should be exhaustive (I added SOME_DEFAULT_VALUE
as a placeholder). I suppose that if you don't know what to put in final else
block you should consider a few options:
optional
and putting none
in the else
,assert
if logically this situation should never happenconst int a = [&] {
if (c1) {
return 1;
} else if (c2) {
return 2;
} else if (c3) {
return -3;
} else {
return SOME_DEFAULT_VALUE;
}
}();
do_something_with(a);
In a situation when the initialization logic duplicates somewhere you can simply extract the lambda to a named function as other answers suggest
In my opinion, the safest option, if you dont want this other value (its just useless), then it may lead to really subtle bug which may be hard to find. Therefore I would throw an expectation when any of the conditions is not met:
int get_init_value(bool c1, bool c2, bool c3) {
if (c1) { return 1; }
else if (c2) { return 2; }
else if (c3) { return -3; }
throw std::logic_error("noone of conditions to define value was met");
}
That way we avoid getting some weird values that want actually match our code, but they would compile anyways ( debugging it may take a lot of time). I consider it way better than just assigning it some clearly wrong value.
Opinion based answer!
I know the example is a simplification of a real, more complex example, but IMHO it seems nowadays this kind of design issue emerge more often, and people sometimes kinda tend to over-complicate it.
Isn't it the whole purpose of a variable to hold some value? Thus isn't having a default value for this variable also a feasible thing?
So what exactly is wrong with:
int a = -1000; // or some other value meant to used for undefined
if (c1) {
a = 1;
} else if (c2) {
a = 2;
} else if (c3) {
a = -3;
}
do_something_with(a);
It is simple and readable... No lambdas, exceptions and other stuff making the code unnecessary complicated...
Or like:
int a;
if (c1) {
a = 1;
} else if (c2) {
a = 2;
} else if (c3) {
a = -3;
} else {
a = -1000; // default for unkown state
}
do_something_with(a);
You could introduce a constant const int undefined = -1000;
and use the constant.
Or an enum if c1, c2, c3 are states in some sort (which it most likely is)...
You could rearrange the code to eliminate the variable if it is not needed elsewhere.
if (c1) {
do_something_with(1);
} else if (c2) {
do_something_with(2);
} else if (c3) {
do_something_with(-3);
}
I would introduce a default value. I'm usually using MAX value of the type for this.
Shortest you can do this with the ternary operator like this:
#include <climits>
int a = c1 ? 1 : c2 ? 2 : c3 ? -3 : INT_MAX;
do_something_with(a);
I understand your real code is much more complicated than the outline presented, but IMHO the main problem here is
should we
do_something_with(a)
at all ifa
is undefined,
rather than
what the initial value should be.
And the solution might be adding explicitly some status flag like a_is_defined
to the actual parameter a
instead of using magic constans.
int a = 0;
bool a_is_defined = false;
When you set them both according to c...
conditions and pass them to do_something()
you'll be able to make a clear distinction between a specific if(a_is_defined) {...}
path and a default (error handling?) else {...}
.
Or even provide separate routines to explicitly handle both paths one level earlier: if(a_is_defined) do_someting_with(a); else do_something_else();
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With