Const T, const T *, T * const, const T &, const T * & difference, const
Here T refers to a data type, which can be basic data types such as int, long, and doule, or class of its own type. A single const must be a constant, but are you confused about the many changes that const joins with other types? Next we will analyze them one by one.
Const T
Defines a constant and must be initialized at the same time. Once declared, this value cannot be changed.
Int I = 5; const int constInt = 10; // correct const int constInt2 = I; // correct constInt = 20; // The constant value cannot be changed to const int constInt3; // error, not initialized
Const T *
A pointer to a constant. It cannot be used to change the value of the object it points.
Const int I = 5; const int i2 = 10; const int * pInt = & I; // correct, pointing to a const int object, that is, the address of I // * pInt = 10; // error. The object pInt = & i2; // which it refers to cannot be changed. It can change the value of the pInt pointer, in this case, pInt points to the i2 address const int * p2 = new int (8); // correct, pointing to the address of a new object delete p2; // correct // int * pInt = & I; // error. I is of the const int type and the type does not match. The const int * cannot be initialized to int * int nValue = 15; const int * pConstInt = & nValue; // correct. int * can be assigned to const int *, but pConstInt cannot change the value of the object to which it points, that is, nValue * pConstInt = 40; // error, cannot change the value of the object to which it points
Difference between const int * and int * const
A pointer itself is an object. Defining a pointer as a constant is a constant pointer, that is, an int * const type. It can also be written as an int * const, which must be initialized during declaration.
Int nValue = 10; int * const p = & nValue; int * const p2 = & nValue; const int * the object to which the Pointer Points cannot be changed, but the value of the pointer itself can be changed; the value of the int * const pointer cannot be changed, but the object to which it points can be changed. Int nValue1 = 10; int nValue2 = 20; int * const constPoint = & nValue1; // constPoint = & nValue2; // The value of constPoint cannot be changed * constPoint = 40; // correct. You can change the object pointed to by the constPoint. In this case, nValue1 = 40 const int nConstValue1 = 5; const int nConstValue2 = 15; const int * pPoint = & nConstValue1; // * pPoint = 55; // error, cannot change the value of pPoint to object pPoint = & nConstValue2; // correct. You can change the value of pPoint pointer, in this case, pPoint states the nConstValue2 object, that is, the pPoint is the address of nConstValue2.
Const int * const is a constant pointer to a constant object, that is, it cannot change the value of the pointer or the object to which the Pointer Points.
Const int nConstValue1 = 5; const int nConstValue2 = 15; const int * const pPoint = & nConstValue1; // * pPoint = 55; // error, the value of the object to which pPoint points cannot be changed. // pPoint = & nConstValue2; // The value of the object cannot be changed.
Const T &
A reference to a constant (const) is also called a constant reference. A constant reference cannot modify its State object.
Int I = 5; const int constInt = 10; const int & rConstInt = constInt; // correct. The referenced and bounded values are constant rConstInt = 5; // error, the referenced object cannot be changed.
A constant reference is allowed to specify a constant object, literal value, or expression. The referenced type must be consistent with the type pointed to by the reference.
Int I = 5; int & rInt = I; // correct, int reference const int constInt = 10; const int & rConstInt = constInt; // correct, the referenced and bounded values are both constant const int & rConstInt2 = rInt; // correct. assign a value of rInt = 30 to an object in the rInt state; // at this time, the rConstInt2, rInt, And I values are all 30 // rConstInt2 = 30; // error, rConstInt2 is a constant reference, rConstInt2 itself cannot change the object int i2 = 15; const int & rConstInt3 = i2; // correct. assign a const int & rConstInt4 = I + i2 to a very large number of objects; // correct. assign a value to the object using an expression, the value is 45i = 20; // at this time, I = 20, rInt = 20, rConstInt4 = 45, indicating that rConstInt4 is the temporary variable const int & rConstInt5 = 50 of I + i2; // positive solution, which is assigned with a constant value
Const T * & T * const &
Reference to a pointer to a constant object, which can be understood in two steps: 1. const T * is a pointer to a constant; 2. const T * & reference to a pointer to a constant.
Const int nConstValue = 1; // constant object const int nConstValue2 = 2; // constant object const int * pConstValue = & nConstValue; // The pointer to the constant object const int * pConstValue2 = & nConstValue2; // the pointer to the constant object const int * & rpConstValue = pConstValue; // reference to the pointer to the constant object // * rpConstValue = 10; // error, rpConstValue points to the constant object, the value of the constant object cannot be changed rpConstValue = pConstValue2; // correct. In this case, the pConstValue value is equal to pConstValue2 // the pointer to the constant object is itself an object, and the reference can change the value of the bounded object int nValue = 5; int nValue2 = 10; int * const constPoint = & nValue; // constant pointer int * const constPoint2 = & nValue2; // constant pointer int * const & rpConstPoint = constPoint; // reference a constant pointer, constPoint // rpConstPoint = constPoint2; // error, constPoint is a constant pointer, and the value of the pointer itself cannot be changed * rpConstPoint = 20; // correct, the object pointed to by the pointer can be changed
Application in Functions
We come up directly from the requirement, assuming there is such a data structure:
typedef struct __Data{ int value;public: __Data() :value(0){}}Data;
1. You want to input an object and do not want the function body to modify it. Method <1>
Void Dealwith (const Data & data) {cout <data. value <endl; // data. value = 5; // error. data is a constant reference and cannot be changed}
This method also has the advantage that only when the function is called will the object be bound, passing the object reference, rather than the object, reducing the cost of object assignment during function calling.
Method <2>
Void Dealwith (const Data * pData) {cout <pData-> value <endl; // pData-> value = 5; // error, pData is a pointer to a constant object and cannot be changed}
This method is the same as void Dealwith (const Data & data ).
Method <3>
Data g_data (20); void Dealwith (const Data * & pData) {cout <pData-> value <endl; // pData-> value = 5; // error, pData is a pointer to a constant object. The pointer to a constant object cannot change pData = & g_data; // correct, pData is a reference to [pointer to a constant object], which can be referenced to change its state}
The call is as follows:
Data d (10); const Data * pData = & d; Dealwith (pData); cout <pData-> value <endl; // at this time, pData-> value is 20, d. value or 10
In this way, the function does not change the value of the passed object, but can return the pointer of another object. Note that the returned pointer must point to a global object. If an object defined in the function is returned, the pointer will be invalid after exiting the function scope, which is very dangerous. If Dealwith is a member function, you can also return a pointer to a Member.
2. for use in a class, return the member of a class, but do not want the caller to modify the member. Method <1>
class MyData{public : MyData(std::string name, Data data) { m_name = name; m_data = data; } const Data* GetData() { return &m_data; }private: std::string m_name; Data m_data;};
The call is as follows:
MyData mydata ("", Data (100); const Data * pData = mydata. getData (); cout <pData-> value <endl; // pData-> value = 100 // pData-> value = 50; // error, pData is a pointer to a constant object and cannot change its value to an object.
Method <2>
Someone may ask GetData to write it as follows:
const Data& GetData(){ return m_data;}
In this case, the caller is often written as follows:
MyData mydata ("", Data (100); Data data = mydata. getData (); // This will have a value assignment process, which will put mydata. m_data is assigned to datacout <data. value <endl; // data. value = 100data. value = 50; // correct, data. value = 50, but mydata. m_data.value or 100
In this way, there will be a result assignment process. If Data is a complex class, there will be a large overhead, and the effect is the same as the following method:
Data GetData(){ return m_data;}
Of course, if the caller uses this method correctly:
const Data& GetData(){ return m_data;}
MyData mydata ("", Data (100); const Data & data = mydata. getData (); // This will have a value assignment process, which will put mydata. m_data is assigned to datacout <data. value <endl; // data. value = 100 // data. value = 50; // error. data is a reference to a constant and cannot change its state object.
This requires a high level of technical capabilities of the caller. If you are a designer, make sure that the interface is easy to use.
Method <3>
If you want to pass in a Data file for some processing, the system returns the m_data member of the class after processing, which can be implemented as follows:
Void DoSomething (const Data * & pData) {if (pData! = NULL) {// doto: the function to be processed is implemented here} pData = & m_data ;}
If you have any questions or thoughts, please give feedback in the comments. Your feedback is the best Reviewer! Due to my limited technical skills and capabilities, if this blog post contains errors or deficiencies, please forgive me and give your valuable suggestions!
If you have any questions or thoughts, please give feedback in the comments. Your feedback is the best Reviewer! Due to my limited technical skills and capabilities, if this blog post contains errors or deficiencies, please forgive me and give your valuable suggestions!