constexpr in vs2015 update 1

Visual Studio 2015 RTM附带对的支持 常量表达式 如C++ 11语言标准中规定的。这个版本从我们的用户和C++社区收到了很多优秀的反馈。使用这个反馈,我们一直在努力改进VS 2015更新1的实现。我们的目标是VS 2015更新1,完成C++ 11 CONTXEPR的最后一个显著特征工作,并提高我们的实现的健壮性。这篇博文将提供一些注释来解释VS2015更新1将我们置于何处 以及我们在constexpr支持下的发展方向。

null

静态初始值设定项

VS 2015附带了一个警告,指出编译器可以检测并使用初始值设定项进行constexpr求值,但不会静态地发出这些初始值设定项。也就是说,虽然编译器有足够的信息来发出完全实例化的类型,这些类型可以从已编译的可执行文件加载,但它没有发出完全实例化的类型。这些类型在运行时被实例化并构造,因为大多数C++对象传统上是这样的。

好消息是VS 2015 Update 1现在支持发射静态初始值设定项!这些类型在加载到内存时会被完全实例化,而不是在运行时运行代码来初始化它们。这是我们需要为C++ 11 CONTHEXPR支持实现的最后一个特性,我们很高兴能用更新1来传送它。

我们应该感谢Tanveer Gani所做的巨大工作,使这个特性与Update 1一起发布。由于他的工作,Update 1将在发布时完全支持为constexpr对象发出静态初始化器。它也将用部分支持来支持具有CONTXPR构造函数的非文字类型对象的不断初始化(如C++语言标准的3.3.2节中所指定的)。具体来说,带有虚拟函数的类型还没有实现。

静态初始化器是实现 std::onceU标志 ,用于 std::给你打一次电话 . 斯蒂芬在他的电话里说 博客文章 关于VS 2015 RTM中STL的改进。

VS 2015 Update 1为运行时执行生成的代码的减少可能非常显著。我想用一些例子来探讨一下这种行为。首先显示C++源,然后是说明静态初始化的汇编代码。这些代码段的程序集是通过调用C++编译器生成的。 /财务会计准则委员会 旗帜。

示例1:Constexpr对象的初始化

我们将从一个简单的示例开始—使用constexpr构造函数构造一个类型的简单实例。

结构 点{ 常量表达式 点(int x1,int y1) :x(x1),y(y1) {}

整数x; 内景; }; 常量表达式 点p1(10,11);

第一, 这个 VS 2015 RTM生成的组件 对于此代码段(用于比较):

; VS 2015 RTM asm 公共??0点@@QEAA@HH@Z ; 点::点 _BSS公司      段 ?p1@@3UPoint@@B DQ 01H重复(?) ; 第1页 _BSS公司      末端 文本$di  段 ??uu Ep1@@YAXXZ程序 ; `“p1”的动态初始值设定项,COMDAT

; 8    : constexpr点p1(10,11);

附属的       rsp,40号 ; 00000028小时 压敏电阻       r8d,11号 压敏电阻       edx,10倍 利亚       rcx,平偏移:?p1@@3UPoint@@B 呼叫      ??0点@@QEAA@HH@Z ; 点::点 添加       rsp,40号 ; 00000028小时 雷特       0 ??uu Ep1@@YAXXZ ENDP ; `“p1”的动态初始值设定项 文本$di  末端

现在VS 2015 Update 1生成的程序集:

; VS 2015更新1 asm 常数  段 ?p1@@3上点@@B DD公司        0啊 ; 第1页 DD公司        0bH公司 常数  末端

请注意,VS 2015更新1中生成的程序集中没有初始化代码。在VS 2015更新1中运行VisualStudio调试器下的C++代码将不会执行针对点的构造函数。

示例2:Constexpr对象数组的初始化

继续上面点的定义,我们将创建一个点数组:

常量表达式 点arr[]={点(2,3),点(5,7),点(11,13)};

VS 2015 Update 1生成的程序集非常出色:

; VS 2015更新1 asm 常数  段 ?排列@@3QBUPoint@@B DD公司          02小时 ; 阿里尔 DD公司          03小时 DD公司          05小时 DD公司          07小时 DD公司          0bH公司 DD公司          0小时 常数  末端

示例3:初始化constexpr对象的指针和引用成员

此代码段使用指向全局constexpr变量的指针和引用初始化constexpr对象。

constexpr int I = 42;struct A {    const int& ref;    const char *ptr;    const char *&ref2;    constexpr A(const char *p, const int& r)    : ref(r), ptr(p), ref2{ptr}    {}};constexpr A a{ "qwerty", I };

此示例实际上在VS 2015 RTM中导致结冰,但会生成 在VS 2015更新1中令人愉快的简洁汇编代码。

; VS 2015更新1 asm 常数  段 ?我@@3HB         DD公司        02安培 ?a@@@3UA@@@B DD公司        平坦:?I@@3HB ; 一 DD公司        单位:2668新加坡元 DD公司        平坦:?a@@3UA@@B+4 2668新元 分贝        ‘qwerty’,00小时 常数  末端

示例4:使用基构造函数初始化constexpr类

即使是具有复杂(非虚拟)继承的类也可以静态初始化。我不打算列出VS 2015 RTM,因为它太长了,但是您可以通过使用 /财务会计准则委员会 旗帜。

结构 空{}; 结构 A{ 短i; 常量表达式 A(内景ii) :一(二) {} }; 结构 B类{ 双d; 常量表达式 B(双di) :d(di) {} }; 结构 空的,A,B{ 双x; 常量表达式 C() :x(1.0)、A(42)、B(-1.0) {} }; 常量表达式 C、C;

以及VS 2015 Update 1生成的程序集:

; VS 2015 Update 1 asmCONST  SEGMENT?c@@3UC@@B DW       02aH                          ; c                ORG $+6                DQ          0bff0000000000000r    ; -1                DQ          03ff0000000000000r    ; 1CONST  ENDS 

示例5:初始化非文本类型

如上所述,一些用常量初始化的非文本类型可以静态初始化。在下面的示例中,提供给constexpr构造函数的initialized是一个常量,因此update1可以静态初始化它。请注意,该类型有一个析构函数,它使该类型成为非文本类型。

extern "C" int puts(const char*);
struct NonLiteralType {
const char *p;
constexpr NonLiteralType(const char *pp)
: p(pp)
{}
 
~NonLiteralType() {
puts("~NonLiteralType()");
}
};
NonLiteralType nlt("qwerty");
int main(){}
 

更新1中生成的程序集未将对象放置在CONST段中,因为它未声明为constexpr:

 

; VS 2015更新1 asm 常数  段 2669新加坡元               分贝          ‘qwerty’,00小时 常数  末端

_数据  段 ?nlt@@3UNonLiteralType@@A DD公寓:$SG2669 ; nlt公司 _数据  末端

使用注册的“atexit”函数销毁非文字类型对象:

; VS 2015更新1 asm CRT$XCU             段 ?nlt$初始值设定项$@@3P6AXXZA DD扁平:??u Fnlt@@YAXXZ ; nlt$初始值设定项$ CRT$XCU             末端 常数  段

文本$yd段 ??uufnlt@@YAXXZ 过程 ; `“nlt”的动态atexit析构函数,COMDAT 推      ebp公司 压敏电阻       ebp,特别是 压敏电阻       ecx,偏移量?nlt@@3UNonLiteralType@@A ; nlt公司 呼叫      ??1非文字类型@@QAE@XZ ; 非文字类型::~非文字类型 流行音乐       ebp公司 雷特       0 ??uu Fnlt@@YAXXZ ENDP`“nlt”的动态atexit析构函数 文本$yd结束

质量改进

除了静态初始化工作之外,我们还修复了约45个与constexpr用法相关的bug。这些缺陷大部分是客户向我们报告的。因为我们试图区分客户问题的优先级,所以在编写constexpr代码时,您应该看到全面的改进,而不是在任何特定领域。下表显示了我们修复的bug。多亏了所有的虫子!

职务 连接客户 康涅狄格州
[constexpr]对成员变量的类使用final将中断constexpr 阿帕雷 1135313
创建constexpr std::array时出现错误C2131 安德烈·阿什赫敏 1574634
constexpr void指针变量未被视为常量 花青素1 1609590
std::array的constexpr失败 布兰登肯特尔 1604956
Constexpr导致内部编译器错误 camhusmj38型 1573435
Constexpr导致内部编译器错误 camhusmj38型 1570534
Constexpr产生错误的结果[与LLVM相比] camhusmj38型 1300591
错误C2131:表达式的计算结果不是常量 camhusmj38型 1596224
MSVC 2015认为constexpr成员指针不是常量 大卫·马涅默 1327934
MSVC 2015在constexpr上下文中的指针算法崩溃 大卫·马涅默 1420558
MSVC 2015尝试评估constexpr构造函数时崩溃 初始化一个引用 大卫·马涅默 1404631
MSVC 2015尝试计算包含指向成员函数的指针的constexpr时崩溃 大卫·马涅默 1327996
MSVC 2015错误地拒绝联合访问的constexpr数组 大卫·马涅默 1323869
MSVC 2015错误地拒绝constexpr上下文中的指针相等 大卫·马涅默 1404624
MSVC 2015在constexpr上下文中实现了一个常量而不是两个常量 大卫·马涅默 1404688
MSVC 2015拒绝初始化对临时对象的constexpr引用 大卫·马涅默 1404715
MSVC 2015拒绝constexpr上下文中const int类型的左值条件运算符 大卫·马涅默 1404674
MSVC 2015拒绝constexpr上下文中的成员指针比较 大卫·马涅默 1401241
MSVC2015拒绝valid并接受无效的constexpr static u cast 大卫·马涅默 1330530
MSVC 2015不会对函数本地静态constexpr引用变量求值 暂时的 大卫·马涅默 1404755
未能使用“constexpr”的有效用法进行编译 dn357型 1311469
std::makeu数组建议实现的constexpr语句中出现编译器故障 菲利克斯·彼得里科尼 1494444
`std::integral_constant<>`隐式定义的默认构造函数和/或`operator value_type`not 常量表达式 伊尔贾恩 1497236
试图在constexpr函数内部进行聚合初始化时,返回临时函数的地址或引用的错误 伊尔贾恩 1498733
C++-COSTEXPR不适用于聚合初始化 伊尔贾恩 1572056
C++-COSTEXPR不与委派构造函数一起工作 伊尔贾恩 1579279
C++定义的静态成员函数在类型定义中被调用时必须完全限定 伊尔贾恩 1579334
C++——用CONTXPR构造函数编写内部编译器错误 伊尔贾恩 1571950
[constexpr]函数指针constexpr推导错误 库什 1378031
在constexpr lambda解决方案中失败 mzer0型 1673865
VC++2015 RTM–带位字段的联合成员的constexpr构造函数错误 奥维德国王 1571281
constexpr和循环模板导致致命错误C1001 彭德纳 1711144
类静态constexpr值为0 pmingkr公司 1384724
constexpr委托构造函数不编译 吉诃德实验室 1229998
与“char const*const”参数相关的constexpr错误 Rui Figueira(云引擎) 1272743
非类型模板实例化的[constexpr][regression][boost]VC++内部编译器错误 萨沙·西特尼科夫 1577162
在constexpr ctor中委托构造函数将无法编译 提交错误报告太难了 1463556
编译此C/C++代码时的ICE
由变量递归constexpr触发的伪错误C2131“表达式未计算为常量”
constexpr委托构造函数
当从结构模板内调用constexpr template函数时,会导致编译失败,并显示错误消息
constexpr 4607“ptr”触发结冰?在constexpr函数中为3:4“

期待

即便是对用更新1进行传输的C++ 11 CONTHEXPR的改进,我们在实现上仍有一些改进。在这个领域,我们的backlog中还有大约30个bug,其中许多与指向常量表达式中成员的指针有关。围绕数组和字符串别名还有一些高质量的工作要做,尽管Tanveer在准备静态初始值设定项方面做得很好,但我们正在计划一些与更改相关的错误报告。

基本上,所有这些都意味着我们将继续工作C++ 11 CysExPR更长的时间,但出色的工作是可管理的。我们的目标是在visualstudio的下一次更新中及时完成这项工作。之后的计划是立即跳入C++ 14的CONTXPR支持。

科迪米勒

Visual C++团队

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享