I do not understand what is going on. I am just learning C++ and I see something like this a lot:
double some_function(const Struct_Name& s) { ... } Why the const if we are passing by reference?
I do not understand what is going on. I am just learning C++ and I see something like this a lot:
double some_function(const Struct_Name& s) { ... } Why the const if we are passing by reference?
You pass by const reference when you don't want to(or can't) modify the argument being passed in, and you don't want the performance hit that you might get from copying the object.
const offers when one is already passing by reference -- allowing temporaries is one of those benefits.)A const reference prevents the object from being modified, as const would anywhere else, but also avoids the potential cost of copying.
(Struct_Name & const s) not like this: (const Struct_Name& s)You are telling the compiler you're not going to change s, ever.
This enables it to make some optimizations it wouldn't have been able to do otherwise. Basically, it gives you the same semantics as passing by value, but doesn't incur the performance penalty of calling the copy constructor.
Call by const-reference avoids a copy of the Struct_Name while promising not to modify it.
There is both a performance reason for this, and a semantics reason.
If Struct_Name is large, copying it is expensive in both time and memory.
If Struct_Name is uncopyable (or becomes invalid when copied) calling by value is impossible or introduces undesirable complexity. For example: std::unique_ptr and std::auto_ptr.
By using const we can signal both the user of the function and the compiler that the object passed as the argument s will not be changed inside the function (which would actually be possible, because we pass it by reference!). The compiler can than give us an error if we modify the object by accident and it can do some optimizations it couldn't do otherwise.
An additional advantage is, that if the caller of the function only owns a const pointer to an object, it can still provide that object as an argument without casting.
const here promisses that some_function will not modify s parameter,
double some_function(const Struct_Name& s) { ... } you can try modifying it but compiler will return errors. Actually constness requires you to carefully write Struct_Name internal methods, ie. you will not be able to call inside some_function non-const functions on s object. You can try, but you will get error. ie:
struct Struct_Name { void myfun() const { } // can be called from some_function void myfun2() { } // will show error if called from some_function }; Using const parameter is good from design point of view, if you know some function is not supposed to change your object then you add const. This means that no other programmer can do changes in some deeply hidden in classes hierarchy code, that will modify your object. It really makes debugging easy.
Another reason that noone has mentioned yet - passing by a const reference allows the compiler to create and pass a temporary object, without generating a warning, if the input value is not the exact type declared in the parameter, but the type has a constructor that supports the type being passed in.
For example:
void foo(const std::string &s) { ... } foo("hello"); // OK foo() is expecting a std::string but receives a const char* instead. Since std::string has a constructor that accept a const char*, the compiler generates code that is effectively doing this:
std::string temp("hello"); foo(temp); The compiler knows the parameter is const, the temporary will not be altered by foo(), and the temporary will be discarded after foo() exits, so it does not complain about having to create a temporary.
The same thing happens if the parameter is passed by value (const or non-const, it does not matter) instead of by reference:
void foo(const std::string s) { ... } void bar(std::string s) { ... } foo("hello"); // OK bar("world"); // OK This is effectively the same as this:
{ std::string temp1("hello"); foo(temp1); } { std::string temp2("world"); bar(temp2); } Again, the compiler does not complain, as it knows the temporary does not affect the calling code, and any alterations made to the temporary in bar() will be safely discarded.
If the parameter were a non-const reference instead, passing a const char* would generate a warning about the temporary that has to be created to satisfy the reference binding. The warning is to let you know that any changes the function makes to the temporary (since it is not const) will be lost when the function exits, which may or may not have an effect on the calling code. This is usually an indication that a temporary should not be used in that situation:
void foo(std::string &s) { ... } foo("hello"); // warning!