This question already has answers here:
Const correctness for value parameters
(6 answers)
Closed 9 years ago.
Say you have:
int f( const T a ) { ... }
int g( const T &a ) { ... }
I understand the use of const in g: we don't know how a is used outside the function, so we want to protect it from being modified. However I don't understand the use of const in f, where a is a local copy. Why do we need to protect it from being modified?
I can think of a few reasons:
1) When someone reads the code and see const T a, they know that a should not be modified in the body of the function.
2) The compiler will tell you when you try to modify a in the body of the function. Therefore, adding const can prevent mistakes.
BTW chris already mentioned this in the comments.
3) However, there is another difference in C++11. A constant object cannot be moved from, as a move operation modifies the object. Therefore, you can only make a copy of a in the function body and cannot move from it.
4) Also, if this is a class type, you cannot call non-const members functions on a const object.
Declaring variables const is a good practice.
WHY?
For arguments passed by value to functions, it doesn't matter for the caller whether you declare it const or not. The rationale here is to protect yourself from mistakes while coding, using the compiler to warn you that you are changing the value of a variable, so that you can explicitly confirm this behavior by removing the const modifier. This applies not only to function parameters, but also to local variables.
Based on this rationale, I personaly always start out by declaring all variables const and let the compiler to issue errors when I modify them. Then I check if this behavior is intended and remove the const modifier if it is indeed needed. For better legibility I also always prefer to code in a way my variables are all const.
"I personally tend to not use const except for reference and pointer parameters. For copied objects it doesn't really matter"
If you are using const in function argument there may be one of the following reason.
1-it help the compiler to optimize things a bit.
2-no body can modified argument value in future(if many people working on same code base)
Related
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!
Pointers and l-value references are exchangeable, for the most part. It's just less to write at the site of invocation.
The difference between const & and & comes, as you noticed, from a simple reference requiring a variable to reference. A reference with & has the semantic of "let me write that down for you". A const & allows the creation of the temporary copy on-the-fly, and has the semantic of "let me have a look". Pass by value has the meaning of "give me a copy, I decide what to do with it".
In practical experience, avoiding copies is your primary concern. So call-by-value is something you want to avoid for anything bigger than an integral value.
Const-correctness is mostly just design of the C++ language, it's not strictly required from a technical point of view. You can consider it to be a way of saying "trust me, I'm not going to break it".
About passing temporary values to a simple & parameter, think about it for a moment who actually owns the temporary, and for how long it's going to exist. Anything written to it, if you would be allowed to do so, would be lost.
Also think about default parameters, e.g. void foo(const bar &foobar = bar(42)). These are never allowed to be non-const references, as it would result in undefined behavior. That default object may live in a static scope (rather than every caller creating it anew), and someone messing with it would result in changing defaults. Good luck ever finding the cause for that bug.
Even for non-default parameters, const & allows the creation of the temporary at compile time (constexpr constructors), and also folding multiple instances of identical temporaries into a single instance in memory. This optimization would likewise not be possible without the guarantees made by const.
There is a plethora of other cases where const-correctness is also the key to enable compiler optimizations. So it's generally better to use correctly, even if you assumed that your code discipline would had prevented at least undefined behavior.
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?
You could also ensure to not make any errors in coding, so why compiler errors/warnings, unit tests, issue trackers, …
Why would you use the keyword const if you already know variable should be constant?
Use const wherever possible in C++?
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?
A class could be more expensive to copy then the indirections over the reference are. Especially if the compiler would be able to inline the function in case of a const & for which no indirection would happen at all.
A copy could introduce unwanted side effects (could be problematic in an environment with limited resources)
A class could have a deleted copy constructor so no copy would be possible at all, but you still want to ensure const correctness.
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?
A pointer can accept a nullptr so you need to handle the case where nullptr is passed (if no nullptr must be passed gsl::not_null could be used). But using pointers would not allow passing temporaries.
This question already has answers here:
Does "const" just mean read-only or something more?
(7 answers)
Closed 8 years ago.
Does
int x = 5;
and
const int cx = 5;
do anything differently at the hardware level? I've never understood that.
In other words, if I declared int x = 5; and then never tried to use x as an l-value anywhere else in my code, would it compile the exact same as if I had declared x constant? Is it just a protection against careless programming?
It's just protection from the programmer. If you do the right messing around with const_cast, you can override const-ness and write to const variables. Assembly code can modify const variables just like anything else. However, if you change the value of a const, the new value may not be visible in all contexts, because compilers aggressively in-line constants.
In certain circumstances it can cause the compiler to use your promise of constness to enable further optimizations.
The best example for this is with static integral values. If they are const as well, the compiler will treat them more like aliases for the value than like variables. In fact, you can utilize this to create values that do not have any addresses at all. An example of this can be found here.
Additionally, const-ness is sometimes used to represent hardware facts in your program: To represent the fact that string literals are oftentimes stored in read only memory, the characters they contain are const.
It is protection against careless programming.
An optimizer may also use it as a hint that certain types of optimizations can be performed, I suppose.
It also tells the compiler that certain things are const which allows you to do stuff like pass temporary instances through reference parameters or as default parameters:
void function (const Object &o) {
}
void another (const Object &o = Object(1234)) {
}
function(Object(5678));
another();
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
is const (c++) optional?
Constant Member Functions
I have seen different posts around about int a() const. My question is exactly why do we want to put the const keyword there? I know that it prevents us from making changes on members of the class the function is in, but so what?
We could just write a comment above the function and tell the coder not to make any changes to the class itself inside the function, but why do we really care about the const after the void declaration? In which scenarios may there be a better way to use for example int a() const instead of just int a() and does the compiled code change at all?
It does make a difference. Consider A to be a class with a print() method. Then this:
const A a;
a.print();
only compiles is print is defined as const.
Of course, the main reason is to prevent any changes to the object inside the class. The
We could just write a comment above the function and tell the coder not to make any changes to the class itself inside the function
is just wishful thinking. This doesn't really happen. So if someone doesn't read the comment (or does and ignores it), you'll get compiler errors.
There's also the benefit of optmization - the compiler can better parallelize tasks on const objects because it can assume they don't change between operations on them.
There are three basic reasons to use const functions:
1) C++ only allows const references can be bound to temporaries. But if you don't have useful const functions, const references are useless.
2) Some libraries, such as the C++ standard library, provide specific semantic guarantees that only apply to const functions. For example, you are guaranteed on standard collections that you can access const functions of the collection from multiple threads concurrently.
3) It allows easy-to-make mistakes to be caught by the compiler. For example, if you intend to rely on the C++ standard container guarantee, if you use a const object, you only can call const functions. So a mistake, say someone modifying the code forgetting about the concurrency issues, will get caught at compile time. (Rather than when someone is relying on your program to do real work.)
The benefit of declaring a member function const is, that the compiler will emit an error, if you modify the object. So, even if you modify the object accidentally, the compiler will catch your mistake.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Const correctness for value parameters
I consider a good coding practice the following. When a parameter is passed to a function by value, it should only be read, but not modified (or reused) in the function body. But is it actually a good practice?
Example (of what I avoid doing):
int foo(int x){
//do lots of cool stuff
x = 69;
//do even cooler stuff
}
From here on we get to const correctness. Provided that my practice is good follows that nearly every argument to every function should be preceded by a "const". Actually "a" is optimistic:
class A{
const int gnoo(const int *const, const double) const;
};
There are two sides to the problem, the declaration and the definition. At the declaration point, the top level qualifiers of the function arguments are dropped, so the const is removed by the compiler. At the definition on the other hand, the compiler ensures that if the parameter is const it will not be modified internally.
The return type is another story, where the const is not dropped from the declaration, but in this case you most probably don't want to make the returned object (if it is by value) const, as that will possibly limit the chances of optimizing of your compiler in a couple of different ways. The first one, brand new in C++11 is that you cannot move out of a const object, which means that by returning a const object you inhibit moving from it. In C++03 the cases where this affect are fewer and more of a corner case, but there is limited advantage on returning const objects.
Some people suggests adding const everywhere. I don't, and most code I have read does not either.
Your point is well taken. And depending on the language, the compiler/interpreter may throw an error or warning when it sees code like your first example.
However, at some point you have to choose whether or not you are going to try and protect "the developers" from doing something stupid or just assume that they are and catch this sort of thing during a code review.
Utilizing syntactic mechanisms to make the code safer is a good thing, IMHO. It can sort of impede development flow, unfortunately.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Sell me on using const correctness
I'm eager to know the answer. [to "What is the benefit of const keyword in programming?"]
const indicates that the value assigned to the variable cannot change. If you try to change the value you should get a compiler error.
The const keyword can declare a read only variable.
Using const parameters to a method tells you the method will not change the parameter.
A const method tells you that the method will not alter a class's member variables (but can change member variables marked as mutable)
You can also declare const pointers, better described here
What is the benefit of const keyword in programming?
Specifying a variable as const states that the variable's value should never change after the initial assignment. This allows the compiler to perform additional tests at compilation (validating your code).
For example, if a const function changes a (non-mutable) member in an object, the compiler will yield an error.
Benefit: You get more compile time checks to ensure that you're not changing data that shouldn't be changed.
Cost: You have to use it everywhere. If you need to, you can cast your way out of it, nullifying the benefits.
Getting usage right can be tricky with pointers. Is the pointer itself const, or the data it refers to? This is also the most common usage I've seen: you want to point to immutable memory.