www.cnblogs.com/myseasky/p/…

Const modifies C++ member functions in three ways: 1. 2. Modify the return value; 3. Decorate the this pointer. Brief knowledge point is as follows, seek kung fu to perfect again later.

1. Modification of function parameters.

1) Const can only be used to modify input parameters. Output parameters cannot be decorated with const.

2) If the input parameter is “pointer passed”, the const modifier protects the pointer from accidental changes.

3) If the input parameter is “value passed”, the function generates a temporary variable (local variable), copies the value of the parameter and pushes it onto the function stack. When this parameter is used in a function, it accesses the value of a temporary variable in the function stack. The original variable is not protected, so do not decorate it with const.

4) Parameters of the basic variable type are used as input parameters of “value passing” without reference. A custom variable type (class type, struct type) argument is used as the input parameter to “value passed”, preferably in the “const+ reference “format of void func (const A& A). The reason is that when custom variable types are passed as values, the design process of creating temporary variables, constructing, copying, and destructing is time-consuming.

Consider the reason in terms of function stack fundamentals. We know that when a function is called, it creates temporary variables for creating each argument and pushes them onto the function stack. If it is a primitive variable type, the temporary variable pushed onto the function stack stores a copy of the argument. If it is a custom variable type, an instance of the type is created on the heap, the argument is copied to the heap, and the address of the instance on the heap is pushed onto the function stack. In the case of a pointer, a copy of the address of the pointer is pushed onto the stack.

That is, the function stack holds either a copy of a primitive type parameter or a top-level pointer. For a parameter stored on the function stack, the copy of the argument can be treated as a normal local variable that can be modified, while for a pointer variable, it can be treated as a top-level pointer whose value cannot be modified, but the value to which it points can be modified.

Therefore, for the basic variable type, the internal operation of the function is the copy on the function stack, and the original value will not be affected. For the class type (non-pointer input parameter), the operation is also the copy of the instance that the address on the function stack points to, and the original value will not be affected. For Pointers, although the function cannot change the value of the pointer stored in the pointer variable (the top-level pointer), the pointer points to the address of the original value, so the original value can be changed.

For a reference, a) a reference is just an alias for a variable. The reference refers to the memory address of the meta-variable. No new memory allocation or copy of the variable is performed. B) Reference declaration must be initialized immediately; C) Once a reference is defined, its value cannot be changed, that is, it cannot be used as a reference to other variables; D) The original variable can be completely manipulated by reference.

As you can see, passing by reference is good for input arguments that take up a lot of space. Because when passing by reference, only an alias of the variable itself is passed, no memory allocation, construction, assignment, destruction and other operations of the new variable are carried out.

If the argument is not allowed to change in the function, then the reference argument should be const.

Based on the above considerations. When const modifies input parameters, it only needs to modify the pointer type and reference type (although it is not mandatory, it should be customary to modify input Pointers or reference parameters with Pointers).

It is also a good programming practice to define a local variable at the beginning of a function to receive input parameters, rather than use them directly.

2. Embellishment of return values.

There are fewer applications. Most return values are passed by value. If the return value is decorated to const, the variable that receives the return value must also be defined as const.

3. Modification of the this pointer.

As we know, c++ member functions pass a this pointer to the instance itself at compile time. This pointer is actually a top-level pointer by default. If classA is present, the pointer looks like this:

classA * const this;

That is, the this pointer points to the instance itself and cannot be modified, but the member variable to which it points can be modified through the this pointer. To access the member variable m_var in a member function, in fact, it has the following form:

this.m_var;

If we design a member function that does not want it to modify the member variable, we should define the this pointer as the underlying pointer. The way c++ defines it is by following the function signature with const, i.e

Void func (const A& A, int b, const int* c, int* d) const;

Obviously, in the above member function, a is passed by const reference and cannot be changed. B is value transfer; C is passed as a const pointer and cannot be changed; D is the output parameter and can be changed. This function is a const member function and cannot change the value of a member variable.

 

Here are a few things to note about const member functions:

1) Const objects can access only const member functions. Nonconst objects can access any member function, including const member functions. So for class A, there are

Const A, A.

So a can only access a const member function. For:

A, b.

B can access any member function.

2) Member variables of const objects cannot be modified.

3) Mutable member variables, which can be modified in any case. That is, const member functions can also modify mutable member variables. C++ is shit is mutable and friendly.

4) Const member functions can access both const and nonconst member variables, but cannot modify any variables. Checking occurs at compile time.

5) A nonconst member function can access a nonconst data member or a const data member of a nonconst object, but not any data member of a const object.

6) Const member functions are only used for non-static member functions, not static member functions.

7) The const modifier of const member functions is added not only to function declarations (including inline functions), but also to functions defined outside the class.

8) As a matter of good programming style, when declaring a member function that does not modify the data member, it should be declared as const whenever possible.

 

——

 

When a C++ programmer sees the const keyword, the first thing that probably comes to mind is const constants. That’s not a good reflex. If you only knew to define constants as const, it would be equivalent to using gunpowder only to make firecrackers. A const has the added benefit of modifying function arguments, return values, and even the body of the function definition.

Const is short for constant, “constant”. Anything decorated with const is forcefully protected against unexpected changes and improves the robustness of the program. So many C++ programming books advise: “Use const whenever you need.”

 

1. Modify function arguments with const

If a parameter is output, regardless of its data type and whether it is passed by pointer or by reference, it cannot be const. Otherwise, the parameter will lose output. Const can only modify input parameters:

If the input parameter is “pointer passed,” the const modifier protects against accidental changes to the pointer.

For example, the StringCopy function:

void StringCopy(char *strDestination, const char *strSource);

StrSource is the input parameter and strDestination is the output parameter. By adding const to strSource, the compiler will point out the error if a statement inside the function tries to alter the strSource’s contents.

If the input parameter is passed by value, it should not be const because the function automatically generates a temporary variable to copy the parameter.

For example, do not write void Func1(int x) as void Func1(const int x). Similarly, do not write void Func2(A A) as void Func2(const A A). A indicates the user-defined data type.

For parameters that are not internal data types, declared functions like void Func(A A) are bound to be inefficient. This is because temporary objects of type A will be generated in the function body to copy parameter A, and the construction, copy, and destruction of temporary objects will take time.

For efficiency, you can change the function declaration to void Func(A & A), because passing by reference only borrows the alias of the parameter and does not need to generate temporary objects. But the void Func(A & A) function has A disadvantage:

Passing by reference has the potential to change parameter A, which we do not expect. It’s easy to fix this by adding const, so the function ends up being void Func(const A & A).

Similarly, should we rewrite void Func(int x) to void Func(const int &x) for efficiency? This is not necessary because there is no construction or destruction of the parameters of the internal data type, and replication is very fast, with “value passing” and “reference passing” almost equally efficient.

The question is so convoluted that I have to summarize the use of the “const &” modifier input parameter.

 

For input parameters that are not internal data types, you should change “value pass” to “const reference pass” to improve efficiency. For example, void Func(A A) is changed to void Func(const A & A).

 

Do not change “value pass” to “const reference pass” for input parameters of internal data types. Otherwise, the efficiency cannot be improved and the comprehensibility of the function will be reduced. For example, void Func(int x) should not be changed to void Func(const int &x).

 

If a pointer is const, the contents of the return cannot be modified. The value can only be assigned to a pointer of the same type as the const modifier. Const char * GetString(void); Char * STR = GetString(); char * STR = GetString(); Const char * STR = GetString(); If a function returns a value that is passed by value, the const modifier has no value because the function copies the return value to an external temporary storage location. For example, don’t write int GetInt(void) as const int GetInt(void). Similarly, do not write the function A GetA(void) as const A GetA(void), where A is A user-defined data type. Rewriting the function A GetA(void) to const A & GetA(void) does improve efficiency if the return value is not an internal data type. Be careful if you want to return a “copy” of the object or just an “alias”, otherwise the program will fail. There are few occasions when a function returns a value by reference. This method is usually found only in the assignment function of a class, for the purpose of chained expression.

For example: class A {A & operate = (const A &other); // assign function}; A a, b, c; // a, b, c = a = b = c; // Normal chain assignment (a = b) = c; // The value of an assignment cannot be modified if the return value of the assignment function is const. In the above example, the statement a = b = c is still correct, but the statement (a = b) = c is illegal.

 

Any function that does not modify a data member (that is, a variable in a function) should be declared as const. If you accidentally modify a data member while writing a const member function, or call another nonconst member function, the compiler will point out the error, which will undoubtedly improve the robustness of the program. In the following program, the member function GetCount of the stack class is used only to count. Logically, GetCount should be const. The compiler will point out the error in the GetCount function. class Stack { public: void Push(int elem); int Pop(void); int GetCount(void) const; // const member function private: int m_num; int m_data[100]; }; int Stack::GetCount(void) const { ++ m_num; // error compiling, attempt to modify data member m_num Pop(); // compilation error, attempt to call nonconst function return m_num; } Const member function declarations look strange: the const keyword should only be placed at the end of the function declaration, presumably because everything else is taken up. A few rules for Const functions: A const object can access only const member functions. Nonconst objects can access any member function, including const member functions. B. Members of const objects are immutable, while objects maintained by const objects through Pointers are modifiable. A const member function may not modify the data of an object, whether or not the object is const. E. A const member function, however, can be modified by any means in any case when a member is mutable.