What is constexpr?

Keywords: C++

Constexpr expression refers to an expression whose value will not change and the calculation result can be obtained during compilation. A variable declared constexpr must be a const variable and must be initialized with a constant expression:

    constexpr int mf = 20;   // 20 is a constant expression
    constexpr int limit = mf + 1; // mf + 1 is a constant expression
    constexpr int sz = size(); // Then, when size is a constexpr function, it is a correct declaration statement

Pointer and constexpr

It must be clear that if a pointer is defined in the constexpr declaration, the qualifier constexpr is only valid for the pointer and has nothing to do with the object to which the pointer refers.

    const int*p = nullptr;         // P is a pointer to an integer constant
    constexpr int* q = nullptr;    // Q is a constant pointer to an integer

  p is a pointer to a constant and q is a constant pointer. The key is that constexpr sets the object it defines as the top const.

    #include <iostream>
     
    int main()
    {
        int i = 10;
        int j = 100;
     
        std::cout << "i=" << i << std::endl;
        
        constexpr int* p = &i;
        *p = 8;
     
        std::cout << "i=" << i << std::endl;
     
        //p = &j; //error
     
        return 0;
    }

The results are as follows:

When using the GNU gcc compiler, the variable referred to by the constexpr pointer must be a global variable or a static variable (i.e. a variable stored in the static data area).

    #include <iostream>
     
    int main()
    {
        static int bufSize = 512;
     
        std::cout << "bufSize=" << bufSize << std::endl;
     
        constexpr int* ptr = &bufSize;
        *ptr = 1024;
        std::cout << "bufSize=" << bufSize << std::endl;
     
        return 0;
    }

ps: the storage areas of global variables and local variables are different. Global variables are stored in the static data area and local variables are stored in the stack area. However, another small point is that variables stored in the static data area are stored from low address to high address, but variables stored in the stack area are stored from high address to low address. Static local variables and static global variables are also stored in the static data area.
 

constexpr function

    constexpr functions are functions used for constant expressions.

    Follow the following rules: (1) the return type of the function and the types of all formal parameters must be literal types; (2) There must be only one return statement in the function body.

#include<iostream>

using namespace std;

constexpr int new_sz() {
    return 42;
}

int main(int argc, char* argv[]) {
    constexpr int foo = new_sz();
    cout << foo << endl;  //42
    getchar();
    return 0;
}

    Analysis: we put new_sz is defined as a constexpr function without parameters. Because the compiler can verify new when the program is compiled_ The SZ function returns a constant expression, so you can use new_ The SZ function initializes the variable foo of type constexpr.

    When this initialization task is performed, the compiler replaces the call to the constexpr function with its result value. In order to expand at any time during compilation, the constexpr function is implicitly specified as an inline function.

    The constexpr function body can also contain other statements, as long as these statements do not perform any operation at runtime (answer?). For example, the constexpr function can have empty statements, type aliases, and using declarations.

constexpr int size() {  //The return value type is literal type
    ; //Empty statement
    using In = int; //using statement
    typedef int INT; //Type alias
    return 10;
}

    We allow the return value of the constexpr function not to be a constant. When the scale argument is a constant expression, its return value is also a constant expression, otherwise:

#include<iostream>

using namespace std;

constexpr int size() {
    ;
    using namespace std;
    typedef int INT;
    return 10;
}

constexpr int new_sz() {
    return 42;
}

//If arg is a constant expression, scale(arg) is also a constant expression
constexpr size_t scale(size_t cnt) {
    return new_sz()*cnt;
}

int main(int argc, char* argv[]) {
    int arr[scale(2)];  //correct
    //int i = 2;
    //int arr2[scale(i)];  // Error: Scale (I) is not a constant expression
    const int j = 2;
    int arr3[scale(j)];  //correct
    getchar();
    return 0;
}

    Put the inline function and constexpr function in the header file:
        Unlike other functions, inline functions and constexpr functions can be defined multiple times in a program. After all, if the compiler wants to expand functions, only function declarations are not enough, but also function definitions. However, for a given inline function or constexpr function, its multiple definitions must be exactly the same. For this reason, inline functions and constexpr functions are usually defined in header files.

Posted by eyegraphix on Tue, 05 Oct 2021 17:53:29 -0700