I was working on a piece of code.
struct Argument
{
Argument(): s_name(""), name(""), optional(true) {}
Argument(String& s_name_inp, String& name_inp, bool optional_inp):s_name(s_name_inp),name(name_inp),optional(optional_inp){}
.....More code.....
}
Somewhere later in the code:
void addArgument(String& name_inp,bool optional=true)
{
String name;
//Creating a tmep string to store the corrected name if the user doesn't enter - or -- wrt. name of their argument.
name = isDashed(name_inp) ? name_inp : addDash(name_inp) ;
//using the dashed name to check if it's shortname or long name.
if(name.size()>3)
{
//This is the long name.
Argument arg("", name, optional);
insertArgument(arg);
}
else
{
//This is for the short name
Argument arg(name, "", optional);
insertArgument(arg);
}
}
Both Struct Argument and fn addArgument are part of a class where struct Argument is defined in the private and addArgument in the public.
It throws up an error when I run the code.. For Long name one-
error: no instance of constructor "ArgumentParser::Argument::Argument" matches the argument list
argument types are: (const char [1], ArgumentParser::String, __nv_bool)
For Short Name one -
error: no instance of constructor "ArgumentParser::Argument::Argument" matches the argument list
argument types are: (ArgumentParser::String, const char [1], __nv_bool)
I could figure out how to fix it. This error is coming because of the empty strings ""
which I enter. Adding const in the struct Argument constructor fixes the problem.
struct Argument
{
Argument(): s_name(""), name(""), optional(true) {}
Argument(const String& s_name_inp, const String& name_inp, bool optional_inp):s_name(s_name_inp),name(name_inp),optional(optional_inp){}
.....More code.....
}
Similarly, declaring a String blank = "" ;
and passing it while initializing an obj of struct Argument instead of ""
curbs the problem as well. Also, passing String instead of String& in the Argument constructor also solves the issue-
Argument(String s_name_inp, String name_inp, bool optional_inp):s_name(s_name_inp),name(name_inp),optional(optional_inp){}
Thus what I concluded from this is that simply passing ""
is a problem since it is not stored in some variable. It doesn't have some location which can be referenced(String&) in case a change is made inside the code. That's why adding a const before String& in the constructor ensures the compiler that no change will be made even though we are passing by ref, so the compiler allows the use of ""
.
However I do not understand why the compiler is being so 'smart' even though I haven't done any incorrect operation. It's like the compiler is popping bugs for 'security' also, apart from the usual 'errors' we make.
With this question, I also want to understand in a broader sense, the use of const
.
I get that it's just for ensuring that no change will be made to the variable being passed(or returned) to a function/constructor. But why do we need it if I, as the programmer, can ensure that I won't be changing the variable. Why do we need const then?
One thing I know is, it can be used to tell others to keep a parameter unchanged if they see your code.(https://www.youtube.com/watch?v=4fJBrditnJU is a good source for learning about const) Also, what is the difference between use of const
in these two cases -
int somefunc const(int& var)
{
// var=4; This isn't allowed due to the const in fn
return var;
}
int somefunc(const int& var)
{
// var =4 ; This is also not allowed.
return var;
}
Also, I want to know how passing by reference and passing by value differ if they are just being used for assignments, i.e, no change is being made to them but they are being used for checking conditions, or doing some assignments to other vars.
Adding const String& is like a surety that whatever the user is passing is not being tampered with, in the code, so can't we simply replace it with String? Because passing by value will instantiate a copy of the passed variable/parameter? Why do we use const String& then?
Another question about passing pointers and passing by reference: The only use I know of String&(or int& or any other) is to directly pass the actual 'thing' into the function, not a copy of it, so whatever we do with that 'thing' will be reflected on the original, just like we use pointers to get the changes to be made to the actual 'thing' and not a copy of it. Why don't we use pointers instead of passing by reference? What advantage does it bring?
I know this question is kind of vast but these are all interconnected questions. Answer to one compliments another. Thanks to anyone who takes the time to answer whatever they seems suitable!