当前位置:网站首页>[C + +] use const as much as possible

[C + +] use const as much as possible

2020-12-07 17:13:43 osc_ 8i2fhl7z

The pointer 、 Iterator and const The relationship between

1.   If the keyword appears to the left of the asterisk , Indicates that the referent is a constant ; If it appears to the right of the asterisk , Indicates that the pointer itself is a constant ; If it appears on either side of the asterisk , Indicates that both the referent and the pointer are constants . If the referent is constant , hold  const  Write before or after the type 、 It was the same before the asterisk .
2.   The function of an iterator is like  T*  The pointer ,const  Before iterator , Iterators can't change , That is to say a statement  T* const  The pointer ;const  Before the iterator variable , The variable referred to by an iterator cannot be changed , That is to say a statement  const T*  The pointer , Need to use  const_iterator.
    vector<int> vec;
    const vector<int>::iterator iter = vec.begin(); 
    //iter Like a T* const
    *iter = 10;     //right
    ++iter;         //iter Can't change 

    vector<int>::const_iterator cIter = vec.begin();
    //cIter Like a const T*
    *cIter = 20;    //*cIter  Can't change 
    cIter++;        //right

In the face of function declaration const

const And function return value

Make the function return a constant value , It can reduce the accident caused by the customer's mistake , Without giving up security and efficiency .

const And function parameters

Unless you need to change parameters or local object , Otherwise, declare the parameter as const


const Member functions

Purpose : Confirm that the member function can act on const object On the body .

Why? ?

1.   send class The interface is easy to understand , You can know which function can change the object content and which function can't 
2.   Can operate const object ,const Member functions can be used to handle the acquired const object , It can also be operated non-const object 

PS: If two member functions are only constant, they are different , It can also be overloaded .

class TextBlock
{
public:
    TextBlock(string str)
    {
        text = str;
    }
    const char& operator[] (size_t position) const
    {
        cout << "call const" << endl;
        return text[position];
    }

    char& operator[] (size_t position)
    {
        cout << "call non-const" << endl;
        return text[position];
    }


private:
    string text;
};

int main()
{
    TextBlock tb("Hello");
    cout << tb[0] << endl;// call non-const
    tb[0] = 'X';    //right           


    const TextBlock ctb("World");
    cout << ctb[0] << endl;// call const
    //ctb[0] = 'X';  //error  Write a const object 
    return 0;

Program output :

 Picture description here

 Also pay attention to ,`non-const operator[]`  The return type is  `char&`  ** If the return type is a built-in type , It's never legal to change the return value of a function **. Even legal , Then according to the pass by value return , What's changed is just a copy of the object , Instead of changing the object itself .

The member function is const What does it mean ?

Two popular concepts :bitwise constness and logical constness

bitwise constness

yes C++ The definition of constancy ,const A member function cannot change any of the non-static Member variables .
One has changed “ What the pointer refers to ” The member function of is not const, But if only the pointer belongs to the object , The object to which the pointer refers does not belong , So call this function bitwise constness The compiler won't object .

using namespace std;
class CTextBlock
{
public:
    CTextBlock(const char text[])
    {
        pText = (char*)malloc(sizeof(char)*strlen(text));
        strcpy(pText,text);
    }
    char& operator[] (size_t position)const
    {
        return pText[position];
    }
private:
    char *pText;
};

int main()
{
    const CTextBlock cctb("Hello");
    char* pc = &cctb[0];
    *pc = 'J';
    cout << cctb[0] << endl;
    return 0;
}

operator The implementation code does not change pText, The compiler determines that it is bitwise constness. Create a constant object , And set the initial value , And just call it const Member functions , however cctb The content of the membership of becomes ”Jello”, After all, it changed its value .

logical constness

One const A member function can modify some of the objects it handles bits, But only if the client can't detect it .

class CTextBlock
{
public:
    CTextBlock(const char text[])
    {
        pText = (char*)malloc(sizeof(char)*strlen(text));
        strcpy(pText,text);
    }
    size_t length() const;
private:
    char *pText;
    size_t textLenght;      // Last calculated text block length 
    bool lengthIsValid;     // Is the current length valid 
};
size_t CTextBlock::length() const
{
    if(!lengthIsValid)
    {
        textLenght = strlen(pText);  //error  
        lengthIsValid = true;       // stay const Cannot assign a value to an object member within a member function 
    }
    return textLenght;
}

Member functions length() Of course not. bitwise const, because textLength and lengthIsValid Can be modified . But the compiler insists it's bitwise const, So there comes error.

resolvent : utilize C++ One of them and const The associated swing field :mutable( Variable ).mutable release non-static Of member variables bitwise constness constraint .
For example, in the above example, it is changed to :

mutable size_t textLength;
mutable bool lengthIsValid;

In this way const In member functions , These variables can also be changed .

stay const and non-const Avoid code duplication in member functions

such as const Completely and non-const The version does the same thing , It's just that there is one more return type const Qualification modification . We want to use this function twice , That is to say, you have to make one call the other .

So who calls who ?

const Member function call non-const A member function is a misbehavior , Because it's possible that the object will be changed ; And the reverse call is safe ,non-const Member functions can do anything with their objects , So we call one const Member functions don't pose risks .

Or to class TextBlock For example :

/* const  Same as before */
const char& operator[] (size_t position) const
    {
        ...
        ...
        ...
        return text[position];
    }

/* non-const  call  const operator[]*/
    char& operator[] (size_t position)
    {
        return 
        const_cast<char&>(
            static_cast<const TextBlock&>(*this)
            [position]
        );
        return text[position];
    }

Two transformations :
1. Put oneself *this From the original type TextBlock& Transformation into const TextBlock&, Use static_cast by *this add const;
2. from const operator[] Remove from the return value of const, use const_cast.

 please remember :
1.   Declare something as const Can help the compiler detect incorrect usage .const  Objects that can be applied to any scope 、 Function parameter 、 Function return type 、 Member function ontology .
2.   Compiler enforcement bitwise constness, But you should use “ conceptual constness ”.
3.   When  const  and  non-const  When a member function has a substantially equivalent implementation , Make non-const  Version call  const  Version to avoid code duplication .

版权声明
本文为[osc_ 8i2fhl7z]所创,转载请带上原文链接,感谢
https://chowdera.com/2020/12/20201207171313144n.html