首页 > 编程语言 >C++11关键字constexpr看这篇就够了

C++11关键字constexpr看这篇就够了

时间:2023-05-22 10:11:05浏览次数:62  
标签:11 tempA const int conTempA C++ constexpr conexprTempA

一、在普通函数中的使用

例如下面的代码,

 

数组的大小必须是常量,在声明数组array时,用函数返回值,此时会报错:

error C2131: 表达式的计算结果不是常数

note: 对未定义的函数或为未声明为“constexpr”的函数的调用导致了故障

用constexpr关键字可以解决这种问题,在GetLen函数前加constexpr声明,代码如下:

 

当然,constexpr修饰的函数也有一定的限制:

     (1)函数体尽量只包含一个return语句,多个可能会编译出错;

       (2)函数体可以包含其他语句,但是不能是运行期语句,只能是编译期语句;

编译器会将constexpr函数视为内联函数!所以在编译时若能求出其值,则会把函数调用替换成结果值。

二、在类的构造函数中也可以使用constexpr关键字

        constexpr还能修饰类的构造函数,即保证传递给该构造函数的所有参数都是constexpr,那么产生的对象的所有成员都是constexpr。该对象是constexpr对象了,可用于只使用constexpr的场合。 

        注意constexpr构造函数的函数体必须为空,所有成员变量的初始化都放到初始化列表中。

        代码如下:

#include <iostream>

using namespace std;

 

class Test 

{

public:

constexpr Test(int num1, int num2) : m_num1(num1), m_num2(num2)

{

 

}

 

public:

int m_num1;

int m_num2;

};

 

int main(void) 

{

constexpr Test t1(1, 2);

 

enum e

x = t1.m_num1, 

y = t1.m_num2 

};

 

return 0;

}

  如果在构造函数中加点代码,就会编译报错,如下:

 

三、const和constexpr对指针的修饰有什么差别呢?

(1)const 和 constexpr 变量之间的主要区别在于:const 变量的初始化可以延迟到运行时,而 constexpr 变量必须在编译时进行初始化。所有 constexpr 变量均为常量,因此必须使用常量表达式初始化。

(2)constexpr和指针

       在使用const时,如果关键字const出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针本身是常量;如果出现在星号两边,表示被指物和指针两者都是常量。

       与const不同,在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指对象无关。

       constexpr是一种很强的约束,更好的保证程序的正确定语义不被破坏;编译器可以对constexper代码进行非常大的优化,例如:将用到的constexpr表达式直接替换成结果, 相比宏来说没有额外的开销。

       代码:

#include <iostream>

using namespace std;

 

int g_tempA = 4;

const int g_conTempA = 4;

constexpr int g_conexprTempA = 4;

 

int main(void)

{

int tempA = 4;

const int conTempA = 4;

constexpr int conexprTempA = 4;

 

/*1.正常运行,编译通过*/

const int *conptrA = &tempA;

const int *conptrB = &conTempA;

const int *conptrC = &conexprTempA;

 

/*2.局部变量的地址要运行时才能确认,故不能在编译期决定,编译不过*/

constexpr int *conexprPtrA = &tempA;

constexpr int *conexprPtrB = &conTempA;

constexpr int *conexprPtrC = &conexprTempA;

 

/*3.第一个通过,后面两个不过,因为constexpr int *所限定的是指针是常量,故不能将常量的地址赋给顶层const*/

constexpr int *conexprPtrD = &g_tempA;

constexpr int *conexprPtrE = &g_conTempA;

constexpr int *conexprPtrF = &g_conexprTempA;

 

/*4.局部变量的地址要运行时才能确认,故不能在编译期决定,编译不过*/

constexpr const int *conexprConPtrA = &tempA;

constexpr const int *conexprConPtrB = &conTempA;

constexpr const int *conexprConPtrC = &conexprTempA;

/*5.正常运行,编译通过*/

constexpr const int *conexprConPtrD = &g_tempA;

constexpr const int *conexprConPtrE = &g_conTempA;

constexpr const int *conexprConPtrF = &g_conexprTempA;

 

return 0;

}

四、对引用的修饰

  代码如下:

#include <iostream>

using namespace std;

 

int g_tempA = 4;

const int g_conTempA = 4;

constexpr int g_conexprTempA = 4;

 

int main(void)

{

int tempA = 4;

const int conTempA = 4;

constexpr int conexprTempA = 4;

/*1.正常运行,编译通过*/

const int &conptrA = tempA;

const int &conptrB = conTempA;

const int &conptrC = conexprTempA;

 

/*2.有两个问题:一是引用到局部变量,不能再编译器确定;二是conexprPtrB和conexprPtrC应该为constexpr const类型,编译不过*/

constexpr int &conexprPtrA = tempA;

constexpr int &conexprPtrB = conTempA;

constexpr int &conexprPtrC = conexprTempA;

 

/*3.第一个编译通过,后两个不通过,原因是因为conexprPtrE和conexprPtrF应该为constexpr const类型*/

constexpr int &conexprPtrD = g_tempA;

constexpr int &conexprPtrE = g_conTempA;

constexpr int &conexprPtrF = g_conexprTempA;

 

/*4.正常运行,编译通过*/

constexpr const int &conexprConPtrD = g_tempA;

constexpr const int &conexprConPtrE = g_conTempA;

constexpr const int &conexprConPtrF = g_conexprTempA;

 

return 0;

}

       简单的说constexpr所引用的对象必须在编译期就决定地址。还有一个奇葩的地方就是可以通过上例conexprPtrD来修改g_tempA的值,也就是说constexpr修饰的引用不是常量,如果要确保其实常量引用需要constexpr const来修饰。

       以上是C++ 11 constexpr的简单应用,要深入学好C++,需要长期的训练,刻意练习。

 

from:https://blog.csdn.net/yao_hou/article/details/109301290

标签:11,tempA,const,int,conTempA,C++,constexpr,conexprTempA
From: https://www.cnblogs.com/im18620660608/p/17419881.html

相关文章

  • 基于C++实现房贷计算器的设计
    访问【WRITE-BUG数字空间】_[内附完整源码和文档]本次项目的要求是完成一个房贷计算器的设计,实现商业贷款、公积金贷款和组合贷款的利息计算三种功能。并且使用Qt或其他的界面库设计人机交互界面,要求界面友好方便使用。并且必须使用面向对象的思想进行设计,使用C++编程。1.题目要求......
  • ICS TRIPLEX工业通讯模块T8110B
    W;① ⑧ 0 ③  0 ① ⑦  7  7 ⑤  9ICSTRIPLEX工业通讯模块T8110B,T8403,T8431,T8403,T8461,T8461C,T8110B,T8403。T8403C,T9432,T9110,T9451,ICSTRIPLEX工业通讯模块T8110B,T8403,T8431,T8403,T8461是电喷发动机控制系统中最重要的传感器之一。发动机转速传感器的作......
  • c++宏
    _Pragmaonce操作符#pragma是一条预处理指令,简单的说他是用来向编译器传达语言标注以外的一些信息例如我们在头文件中定义了如下语句#pragmaonce则表示该指令会指示编译器该头文件只会被编译一次(保证头文件只被include一次)而c++11中定义了与#pragma功能相同的操作符_Pgram......
  • 2022.11.24 NOIP模拟赛
    A.不降序列题目描述lzx2005了解到有一种在\(O(n\logn)\)的时间复杂度内求出一个序列\(a\)的最长不下降子序列的方法如下:维护一个序列\(b\),初始时为空。依次考虑\(a_1,a_2,\ldots,a_n\),当考虑到\(a_i\)时,求出序列\(b\)中第一个比\(a_i\)大的元素,然后使用\(a_i......
  • 2022.11.23 51nod 图论专场?
    A反转Dag图:题面给出一个\(n\)个点\(m\)条边的有向图,顶点编号\(1\)到\(n\),边的编号为\(1\)到\(m\)。你可以选择一些边进行反转(即从\(u\)到\(v\)的边反转后变为从\(v\)到\(u\)的边),将每条边反转都需要一定代价。最终使得整个图变成一个\(Dag\)图。总的反......
  • C++ 测试框架 GoogleTest 初学者入门篇 甲
    *以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「ENG八戒」https://mp.weixin.qq.com/s/BS_u9A4EY50y4vDDuxkCAQ开发者虽然主要负责工程里的开发任务,但是每个开发完毕的功能都是需要开发者自测通过的,所以经常会听到开发者提起单元测试的话题。那么今天我就带大伙......
  • 【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针
    文章首发【重学C++】02脱离指针陷阱:深入浅出C++智能指针前言大家好,今天是【重学C++】系列的第二讲,我们来聊聊C++的智能指针。为什么需要智能指针在上一讲《01C++如何进行内存资源管理》中,提到了对于堆上的内存资源,需要我们手动分配和释放。管理这些资源是个技术活,一不小......
  • 微软推出Windows 11 Insider预览版22621.1255和22623.1255
    您好,WindowsInsider,今天我们将向Beta频道发布Windows11Insider预览版22621.1255和22623.1255(KB5022918)。Build22623.1255=推送新功能。Build22621.1255=默认情况下关闭新功能。提醒:以前在22622版本上的内部人员将通过启用包自动转移到22623版本。启用包人为地增加了新功能推出......
  • 详解C++STL—函数对象
    1、函数对象1.1、函数对象概念概念:重载函数调用()操作符的类,其对象常称为函数对象函数对象使用重载的()时,行为类似函数调用,也叫仿函数本质:函数对象(仿函数)是一个类,不是一个函数1.2、函数对象的使用特点:函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值函数对象超......
  • 为什么只有Python可以爬虫,C++可以吗?
    Python(英国发音:/ˈpaɪθən/;美国发音:/ˈpaɪθɑːn/),是一种广泛使用的解释型、面向对象、动态数据类型的高级程序设计语言。Python支持多种编程范型,包括结构化、过程式、反射式、面向对象和函数式编程。它拥有动态类型系统和垃圾回收功能,能够自动管理内存使用,并且其本身拥有一个......