首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >常量表达式未定义的行为

常量表达式未定义的行为
EN

Stack Overflow用户
提问于 2011-09-15 02:27:45
回答 2查看 1.2K关注 0票数 18

我一直在用constexpr做实验。在我的测试编译器(g++ 4.6)上,这无法编译,并出现关于越界访问的错误。编译器是否需要在编译时发现这一点?

代码语言:javascript
复制
#include <iostream>

constexpr const char *str = "hi";

constexpr int fail() {
  return str[1000]; // Way past the end!
}

template <int N>
struct foo {
  static void print() { std::cout << N << std::endl; }
};

int main() {  
  foo<fail()>::print();
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-09-15 07:59:09

§5.19/2 (在第二页;它确实应该分成许多段落)禁止包含以下内容的常量表达式

-左值到右值的转换(4.1),除非将其应用于

-整型或枚举型的glvalue,引用具有先前初始化、使用常量表达式初始化的非易失性常量对象,或

-文本类型的GL值,它引用了用constexpr定义的非易失性对象,或者引用了这样的对象的子对象

与边界数组访问不同,str[1000]转换为* ( str + 1000 ),它不引用str的子对象。因此,这是一个可诊断的规则,编译器需要发出错误。

编辑:关于这个诊断是如何产生的,似乎有一些困惑。当表达式需要为常量时,编译器根据§5.19检查该表达式。如果表达式不满足要求,编译器就会被要求报错。实际上,需要针对任何可能导致未定义行为的常量表达式进行验证。*这可能涉及也可能不涉及尝试计算表达式。

*在C++11中,“一个没有数学定义的结果”。在C++14中,根据定义(§1.3.24),“具有未定义行为的操作”忽略了实现可能定义为回退的行为。

票数 11
EN

Stack Overflow用户

发布于 2014-01-24 05:23:02

是的,编译器应该在编译时捕捉到这一点,如果我们查看draft C++ standard5.19常量表达式部分第2段,它会将其列为常量表达式的排除项:

-一种具有未定义行为的操作注:包括,例如,带符号整数溢出(第5条)、某些指针算术(5.7)、除零(5.6)或某些移位操作(5.8) -end注释;

据我所知,issue 695说未定义的行为是非常量,应该发出诊断:

CWG的共识是,像1/0这样的表达式应该简单地被认为是非常量;任何诊断都将导致在需要常量表达式的上下文中使用该表达式。

你可以在我的self answered question here上找到更多细节,它也介绍了这个功能的用法。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7421170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档