- C++ Fundamentals
- Antonio Mallia Francesco Zoffoli
- 889字
- 2021-06-11 13:36:00
Const Parameters and Default Arguments
In the previous chapter, we saw how and when to use references in function parameters and return types. C++ has an additional qualifier, the const qualifier, which can be used independently from the ref-ness (whether the type is a reference or not) of the type.
Let's see how const is used in the various scenarios we investigated when looking at how functions can accept parameters.
Passing by const Value
In pass by value, the function parameter is a value type: when invoked, the argument is copied into the parameter.
This means that regardless of whether const is used in the parameter or not, the calling code cannot see the difference.
The only reason to use const in the function signature is to document to the implementation that it cannot modify such a value.
This is not commonly done, as the biggest value of a function signature is for the caller to understand the contract of calling the function. Because of this, it is rare to see int max(const int, const int), even if the function does not modify the parameters.
There is an exception, though: when the function accepts a pointer.
In such cases, the function wants to make sure that it is not assigning a new value to the pointer. The pointer acts similar to a reference here, since it cannot be bound to a new object, but provides nullability.
An example could be setValue(int * const), a function that takes a const pointer to an int.
The integer is not const, so it can be changed, but the pointer is const and the implementation cannot change it during implementation.
Passing by const Reference
Const is extremely important in pass by reference, and any time you use a reference in the parameters of a function, you should also add const to it (if the function is not designed to modify it).
The reason for this is that a reference allows you to modify the provided object freely.
It is error-prone, since the function might modify an object the caller does not expect to be modified by mistake, and it is hard to understand as there is no clear boundary between the caller and the function, again, because the function can modify the state of the caller.
const instead fixes the problem, since a function cannot modify an object through a const reference.
This allows the function to use reference parameters without some of the drawbacks of using references.
The function should remove the const from a reference, but only if it is intended to modify the provided object, otherwise every reference should be const.
Another advantage of const reference parameters is that temporary objects can be used as arguments for them.
Returning by const Value
There is no widespread reason to return by const value since the calling code often assigns the value to a variable, in which case the const-ness of the variables is going to be the deciding factor, or passes the value to a next expression, and it is rare for an expression to expect a const value.
Returning by const value also inhibits the move semantic of C++11, thus reducing performance.
Returning by const Reference
A function should always return by const reference when the returned reference is meant to only be read and not be modified by the calling code.
The same concept we applied to object lifetimes when returning references to them also apply to const:
- When returning a reference accepted as a parameter, if the parameter is a const reference, the returned reference must be const as well
- When returning a reference to a part of an object accepted as the const reference parameter, the returned reference must be const as well
A parameter accepted as a reference should be returned as a const reference if the caller is not expected to modify it.
Sometimes, the compilation fails, stating that the code is trying to modify an object that is a const reference. Unless the function is meant to modify the object, the solution is not to remove const from the reference in the parameter. Instead, look for why the operation that you are trying to perform does not work with const, and what the possible alternatives are.
const is not about the implementation, it is about the meaning of the function.
When you write the function signature, you should decide whether to use const, as the implementation will have to find a way to respect that.
For example:
void setTheThirdItem(std::array<int, 10>& array, int item)
This should clearly take a reference to the array since its purpose is to modify the array.
On the other hand, we can use the following:
int findFirstGreaterThan(const std::array<int, 10>& array, int threshold)
This tells us that we are only looking into the array – we are not changing it, so we should use const.
Note
It is a best practice to use const as much as possible, as it allows the compiler to make sure that we are not modifying objects that we do not want to modify.
This can help to prevent bugs.
It also helps to keep another best practice in mind: never use the same variable to represent different concepts. Since the variable cannot be changed, it is less natural to reuse it instead of creating a new one.
- Mastering Concurrency Programming with Java 8
- Drupal 8 Blueprints
- Monkey Game Development:Beginner's Guide
- Spring Cloud Alibaba微服務架構設計與開發實戰
- 單片機C語言程序設計實訓100例:基于STC8051+Proteus仿真與實戰
- 信息安全技術
- Mastering Unity Shaders and Effects
- Mastering Ext JS
- Django 3.0應用開發詳解
- Java Web應用開發項目教程
- SQL Server實例教程(2008版)
- INSTANT PLC Programming with RSLogix 5000
- Visual FoxPro數據庫程序設計
- PHP典型模塊與項目實戰大全
- 秒懂算法:用常識解讀數據結構與算法