Explanation of c ++ Constants
Concept
Constants are fixed and immutable values. Once an initial value is determined, it cannot be changed elsewhere in the program. Therefore, the const object must be initialized. Constants are usually modified using the const keyword.
Const objects can be roughly divided into three types:
1. const int
Const int a = 10;
Int const B = 10;
The two formats are identical. That is to say, const and int do not affect semantics before writing. With this concept, let's look at the two guys: const int * pi and int const * pi. Are their meanings different?
You just need to remember that int and const are the same before and after the put, just like const int n; and int const n. That is to say, they are the same.
2. const int * p
As mentioned above, const int * p is exactly the same as int const * p.
Let's take a look at their meanings based on the examples below.
Int a = 30;
Int B = 40;
Const int * p = &;
P = & B; // note that p can assign a new memory address at any time.
B = 80; // think about it: Can I use * pi = 80; instead? Of course not.
Printf ("% d", * p); // The output is 80
Semantic Analysis:
The value of p can be modified. That is, it can point to another address again, but it cannot use * p to modify the value of B.
First, const modifies the entire * p (note that it is * p rather than p ). Therefore, * p (the object pointed to by p) is a constant and cannot be assigned a value (although p refers to B as a variable, not a constant ).
Second, p is not modified with const, so p is a pointer variable and can be assigned a value to point to another memory address.
You may wonder: how can I use const to modify pi? In fact, you can understand the position of the const In the int * const pi. Remember to view the semantics through the format. Let's take a look at the definition below.
3. int * const p
Here, the const modified p instead of the above * p. We will analyze it based on the example below:
Int a = 30;
Int B = 40;
Int * const p = &;
// P = & B;
Note that p can no longer be assigned in this way, that is, it cannot point to another new address.
B = 80;
// Can I use * p = 80; instead? Yes. Here, you can use * p to modify the value of.
// Compare it with the previous example.
Printf ("% d", * p); // The output is 80
* P = 100;
Printf ("% d", a); // The output is 100
Semantic Analysis:
The P value cannot be changed. It can only always point to the memory address during initialization. You can use * p to modify the value of. Compare it with the previous example! See the following two points for analysis:
1). p is a pointer constant because of the const modification: that is, the p value cannot be modified (that is, p cannot point to the variable B again ).
2). There is no const modification before the entire * p. That is to say, * p is a variable rather than a constant, so we can use * p to modify the value of memory.
In a word, p is a pointer constant pointing to int variable type data.
The last two sentences are summarized:
1) if const is modified before * p, it cannot be changed to * p instead of p.
2) If const is directly written before p, p cannot be changed.
4. Add three cases.
Here, I will add the following three cases. In fact, as long as the above semantics is clear, these three situations have already been included. But as three specific forms, I 'd like to mention it briefly!
Case 1: int * When the pi Pointer Points to the const int n constant
Const int n1 = 40;
Int * pi;
Pi = & n1; // Can this be true? No. It is a compilation error in VC. The address of const int type n1 cannot be assigned to the pointer pi pointing to the int type address. Otherwise, won't pi be able to modify the n1 value!
Pi = (int *) & n1; // Can this be true? Forced type conversion is supported by C. The n1 value cannot be modified through * pi = 80. Try it! Let's see how it works.
Case 2: When the const int * pi Pointer Points to const int n1
Const int n1 = 40;
Const int * pi;
Pi = & n1; // The two types are the same. You can assign values like this. The n1 value cannot be modified either through pi or n1.
Case 3: pointer declared with const int * const pi
Int n;
Const int * const pi = & n;
// Can you imagine what operations pi can perform? The pi value cannot be changed or the value of n cannot be changed through pi. Because no matter
// * Both pi and pi are const.
5. constant reference
Int a = 10;
Int & p1 = a; // correct
Int & p2 = 2; // error. The left value must be referenced.
Const int & p3 = a; // correct
Const int & p4 = 4; // correct
There are two points worth noting about the initialization of the reference:
(1) When the initialization value is a left value (address can be obtained), there is no problem. You can use a constant reference or a constant reference, such as p1 or p3;
(2) When the initialization value is not a left value, only oneConstT & (constant reference) value assignment. Such as p2 and p3. In addition, this assignment has a process:
First, the value is implicitly converted to the type T, and then the conversion result is stored in a temporary object. Finally, this temporary object is used to initialize the reference variable.
If a constant is referenced, the compiler first creates a temporary variable and then places the value of the constant into the temporary variable. The referenced operation is the operation on the temporary variable. The constant reference can be initialized with any other reference, but cannot be changed.
6. Constant functions, constant reference parameters, and constant reference return values
Example 1: bool verifyObjectCorrectness (const myObj & obj); // const reference parameter
Example 2: void Add (const int & arg) const; // const function
Example 3: IStack const & GetStack () const {return _ stack;} // return const reference
6.1 constant Functions
1. A function is declared as a constant function by adding the keyword const.
2. In C ++, it is meaningful to declare a member function as a constant function. A constant member function with the const suffix is also called an inspector.
Mutator is a mass member function with a const suffix)
3. const-related errors are always found during compilation
4. [Abstract] If the function is not declaredconst
, In can not be applied to a const object, and the compiler will
Give an error message.const
Function can be applied to a non-const
Object
5. In C ++, all methods of an object receive an implicit this pointer pointing to the object itself. The constant method obtains an implicit constant this pointer.
Void func_name () const;
The preceding description shows that the function func_name () does not change * this. When you think of this pointer as an invisible parameter of function func_name (), you will understand it.
Void func_name (T * this) (no const)
Void func_name (const T * this) (const)
6. Constant functions can be called by any object, while non-constant functions can only be called by non-constant objects and cannot be called by constant objects, for example:
class Fred { public: void inspect() const; // This member promises NOT to change *this void mutate(); // This member function might change *this }; void userCode(Fred& changeable, const Fred& unchangeable) { changeable.inspect(); // OK: doesn't change a changeable object changeable.mutate(); // OK: changes a changeable object unchangeable.inspect(); // OK: doesn't change an unchangeable object unchangeable.mutate(); // ERROR: attempt to change unchangeable object }
7. Constant functions and non-constant functions with the same name are allowed in the class. The Compiler selects an appropriate function based on the object that calls the function.
When a very large object calls this function, it first calls the very large function;
When a constant object calls this function, it can only call a constant function;
If there is only a constant function in the class and there is no constant function with the same name, then both the constant and the constant object can call this constant function. For example:
# Include <iostream> using namespace std; struct A {void f () const {cout <"const function f is called" <endl;} void f () {cout <"non-const function f is called" <endl;} void g () {cout <"non-const function g is called" <endl ;}}; void main () {A; const a & ref_a = A;. f (); // callvoid f (), output: non-const function f is called
Ref_a.f (); // callvoid f () const, output: const function f is called
a.g(); //ok, normal call
ref_a.g(); //error, const object can not call non-const function }
8. The const keyword cannot be used in constructor and destructor. Because the purpose of the constructor is to initialize the Domain value, it must change the object. The same is true for the destructor.
6.2 constant reference parameters
In this example, an object of the myObj type is referenced to pass in the verifyObjectCorrectness function. For security, the const keyword is used to ensure that the verifyObjectCorrectness function does not change the state of the object referenced by object obj. In addition, by declaring parameter constants, function users can ensure that their objects are not changed, and do not have to worry about side effects when calling the function. The following code tries to modify the parameter declared as a constant reference, so that it will not pass compilation!
# Include <iostream> using namespace std; class Test {public: void f (const int & arg); private: int value ;}; void Test :: f (const int & arg) {arg = 10; // try to modify the arg value. This line will cause a compiler error/error C2166: l-value specifies const object cout <"arg =" <arg <endl; value = 20;} void main () {int I = 7; Test; test. f (I); cout <"I =" <I <endl ;}
6.3 return value of constant reference
If you want to return a Member of this object from the constant method (function), you should use the constant reference to return it, that is, const X &
That is to say, if you want to reference the returned content as part of this object logically (it has nothing to do with whether it is physically embedded in this object ), then, the constant method must be returned through constant reference or value, but not through constant reference.
class Person {public: const string& name_good() const; // Right: the caller can't change the name string& name_evil() const; // Wrong: the caller can change the name .};void myCode(const Person& p) // You're promising not to change the Person object{ p.name_evil() = "Igor"; // but you changed it anyway!!}