C++ constexpr的使用小结

 更新时间:2026年02月08日 09:56:47   作者:Sichg  
constexpr是C++的修饰词,用于指定编译期可以求数值的常量表达式,可用于修饰变量,函数,类/结构体,构造函数/析构函数,模板五种情况,下面就来详细的介绍 一下如何使用

constexpr是C++的修饰词,用于指定“编译期可以求数值的常量表达式”,可用于修饰变量,函数,类/结构体,构造函数/析构函数,模板五种情况,作用就是支持编译期常量处理。constexpr的实际应用中最常用的是修饰变量和函数。

  • constexpr用于修饰变量,可以构建真常量,即编译器常量。
  • constexpr用于修饰函数,可以用于编译期求值;
  • constexpr用于修饰类/结构体。可以用来在编译期构造对象;
  • constexpr用于修饰构造函数/析构函数,可以在编译器就对类对象进行初始化/销毁;
  • constexpr用于修饰模板,在编译期间完成模板实例化进行求数值。

增加编译期间求解的效果是提升性能、增强类型安全。

实例1——constexpr修饰变量:

#include <iostream>
constexpr int MAXsize = 100; // 由constexptr修饰的int型真常量,
//在编译期就可以通过直接赋值确定取值为100.
constexpr int OVERsize = MAXsize + 50;
//在编译期可以通过计算得到确定取值为150.
//由constexpr修饰的MAXsize和OVERsize两个真常量,分别取值100和150.
//编译正常。符合处理直觉。

提问: constexpr 可以修饰变量,此时该变量是编译期常量(值必须在编译期确定,且生命周期内不可修改,比 const 更严格)如果这个变量的取值在编译期间没有确定会报错吗?还是任意给这个变量取定一个随机值?取定随机值会导致这个变量实际没有可用效果? 以及这里讲的生命周期不可修改是什么意思?一个constexpr修饰的真常量的生命周期不就是整个程序运行的期间都有效吗?编译期常量即真常量是不占用C++堆内存和栈内存的吧!

解答:
// constexpr 修饰变量,这个变量的数值必须在编译期确定,生命周期内不可修改。
// 如果编译期间这个变量的数值没有确定指定,会直接编译报错,无随机值。
// constexpr 修饰得到的真常量在生命周期内都只具有只读属性,不可修改。
// constexpr 修饰得到的真常量的生命周期取决于变量定义所在的作用域决定。
    // 即constexpr只负责跟编译器通力合作在编译期间确定数值。
    // 至于这个真常量在何时失效取决于这个变量的自身的作用域,
    // 即定义在函数内部的变量,即便加上constexpr修饰,
    // 这个真常量的生命周期依然只在函数内的局部作用域效果下。constexpr修饰的真常量被存储在静态只读数据区。

总结1:

  • constexpr修饰变量,得到真常量,存储在静态存储区,不占用运行内存;(因此增强性能)
  • constexpr修饰得到的真常量,如果没有在编译期指定,直接报错。
  • constexpr修饰得到的真常量,生命周期内权限为只读,不可修改。
  • constexpr修饰得到的真常量,生命周期长度取决于变量本身的生命周期。

实例2——constexpr修饰函数:

表示这个函数,如果入参是编译期常量,在编译期完成计算得到处理结果。如果入参不是编译期间常量,那就退化成普通函数。两种情况都不会报错。UDL和普通函数都支持这种退化兼容。

//constexpr修饰UDL(自定义字面值运算符)
constexpr long long operator "" _KM2m(long long kilometer) {
    return kilometer*1000;
}
//constexpr修饰普通函数
constexpr int add(int a, int b){
    return a + b;
}

实例3——constexpr修饰类/结构体:

作用是在编译期构造类对象,即编译期常量对象。 要求:

  • 类的构造函数必须是constexpr构造函数;
  • 编译期内需调用的成员函数也必须有constexpr修饰;
  • 类的成员变量中,对于被constexpr使用/依赖的静态成员变量,必须在类内constexpr修饰。而且最好直接用static constexpr
//constexpr修饰结构体(在C++中将结构体视为类的一种)
struct Point{

    //constexpr 修饰构造函数
    constexpr Point(int x_, int y_) : x(x_), y(y_) {}
        // C++中约定俗成用 变量名右加下划线 表示类成员变量的命名。
        // x(x_), y(y_) 是 C++ 中的「成员初始化列表(Member Initialization List)
            // 效果是将x_,y_的值对应赋值给x,y
            // `x(x_)` 和 `x=x_` 在初始化列表中等价
            
    //constexpr 修饰构造函数
    constexpr int get_x() const {
        return}
    }
    
    int x;
    int y;
   }
   
   int main () {
       //编译器构造Ponit对象
       constexpr Point p0(10,20);
       //编译期调用成员函数,获取数值
       constexpr int x_val = p0.get_x(); 
       return 0;
   }
  • 非静态成员变量是指属于单个对象的变量,每个对象独一份,生命周期随对象变化;
  • 静态成员变量属于类本身的,所有对象共享一份,生命周期贯穿程序。
    • 静态const成员变量:类内直接初始化,因为贯穿程序的生命周期,且在运行期间数值不可修改,是绑定在整个类上的变量。static const 变量类型 变量名 = 初始化数值;
      • static constexpr 变量类型 变量名 = 初始化数值; 效果更好。
    • -这里的static其实是指类共享。静态变量本质是类共享变量;非静态变量是类不共享变量。

实例4——constexpr修饰构造函数/析构函数:

构造函数用constexpr修饰,要么非空要么只涉及基本四则运算和判断的简洁函数体。 析构函数用constexpr修饰,得到的效果是编译期对象销毁时没有运行期开销。 (constexpr修饰的效果要么是用于设定真常量,要么是能在编译期间能处理的事情给处理了。)

class MyInt{

    public: 
        //构造函数
        constexpr MyInt (int val_) : val(val_) {}
        //析构函数
        constexpr ~MyInt() = default; //析构函数直接 = default 就行。
        //成员函数
        constexpr int get_val() const {
            return val;
        }

    private:
        int val;
};

int main() {
    //在编译期构造 MyInt 对象
    constexpr MyInt mi(100);
    constexpr int val = mi.get_val(); // 编译期求值为100
    return 0;
}

关联说明类成员函数的const尾缀修饰: constexpr int get_val() const { return val; //这个const成员函数只读取,没有修改val的权限。 }

const成员函数

作用是限定这个成员函数对成员变量的操作权限仅仅是只读。

  • 禁止修改类的非静态成员变量,确保这个函数只进行只读操作,不会改变对象的状态。
  • 禁止调用非const成员函数。

const是 “承诺不修改成员变量”,仅支持运行期执行;constexpr是 “支持编译期求值”,

实例5——constexpr修饰模板template:

使模板实例化后具备编译器求值能力。

template <template T>
    constexpr T max_val(T a, T b){
        return a > b ? a : b;
    }
    
int main() {
    constexpr int max_num = max_val(5,10);
    //编译期求值: max_val(5,10)实例化得到int型数据,取值为10.
    return 0;
}

到此这篇关于C++ constexpr的使用小结的文章就介绍到这了,更多相关C++ constexpr内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入了解C语言字符函数和字符串函数

    深入了解C语言字符函数和字符串函数

    这篇文章主要给大家介绍了关于C语言字符/字符串的相关函数,文中通过示例代码总结的非常详细,对大家学习或者使用C语言具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2021-07-07
  • 基于C语言实现点菜系统

    基于C语言实现点菜系统

    这篇文章主要为大家详细介绍了基于C语言实现点菜系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • c++动态库调用的实现

    c++动态库调用的实现

    本文主要介绍了c++动态库调用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • c语言内存泄露示例解析

    c语言内存泄露示例解析

    从1988年著名的莫里斯蠕虫 攻击到有关 Flash Player 和其他关键的零售级程序的最新安全警报都与缓冲区溢出有关:“大多数计算机安全漏洞都是缓冲区溢出”,Rodney Bates 在 2004 年写道
    2013-09-09
  • C++实现循环队列和链式队列的示例

    C++实现循环队列和链式队列的示例

    下面小编就为大家分享一篇C++实现循环队列和链式队列的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • C++模拟实现vector的示例代码

    C++模拟实现vector的示例代码

    大家在学习C++的时候一定会学到STL(标准模板库),这是C++标准库中最重要的组成部分,它包含了常用的数据结构和算法。今天呢,我们首先来学习STL中的vector容器
    2022-09-09
  • C语言实现随机生成6位数密码

    C语言实现随机生成6位数密码

    这篇文章主要为大家详细介绍了如何使用C语言实现一个简单而实用的随机密码生成器,该生成器将生成包含字母、数字和特殊字符的随机密码,有需要的小伙伴可以参考下
    2023-11-11
  • 详解如何在code block创建一个C语言的项目

    详解如何在code block创建一个C语言的项目

    这篇文章主要介绍了详解如何在code block创建一个C语言的项目,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • C++ ofstream与ifstream详细用法

    C++ ofstream与ifstream详细用法

    ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间
    2013-07-07
  • C语言函数指针详解

    C语言函数指针详解

    大家好,本篇文章主要讲的是C语言函数指针详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01

最新评论