受到“使用编译时 HTML 解析的 C++ HTML 模板引擎 https://github.com/rep-movsd/see-phit“,我正在尝试编写一个示例类来检查字符串中的第一个字符是否是a
.
int dummy[0];
class Test
{
public:
constexpr Test(const char *p):p_(p){}
constexpr void check()const
{
if (p_[0]!='a')
dummy[1]=0;
}
const char *p_;
};
constexpr Test operator"" _test(const char *pszText, size_t)
{
Test t(pszText);
t.check();
return t;
}
int main()
{
//dummy[1] = 0;
constexpr Test t = "baa"_test;
}
它运行良好(Ubuntu 上的 GCC7.1)。如果第一个字符不是a
,它会给出编译错误:
main.cpp:29:24: error: array subscript value ‘1’ is outside the bounds
of array ‘dummy’ of type ‘int [0]’
constexpr Test t = "baa"_test;
让我困惑的是,如果我将代码更改为:
int main()
{
dummy[1] = 0; //no compile error anymore
}
我想知道 C++ 何时报告数组越界错误。
constexpr
要求编译器评估代码。而且,因为,在 C++ 抽象机的上下文中,dummy[1]
是未定义的行为,它必须发出诊断。 (这可以是警告也可以是错误。但是,两者g++
and clang++
选择将此设置为错误。)
然而,仅仅因为dummy[1]
在 C++ 抽象机的上下文中是未定义的行为,并不意味着其他东西没有定义该行为。这意味着代码不一定会被拒绝(如果编译器本身不需要使用它)。这只是未定义的行为,而不是错误。
例如,编译器编写者将使用越界数组访问,并且因为他们正在编写编译器,所以他们可以确保发生的行为是所需的行为。一个很好的例子是数组内存管理,其中返回的指针通常是已分配内存开头的一个字(因为大小也需要分配。)因此,当编译器编写者需要读取大小时,他或她可能会这样做((size_t const*)ptr)[-1]
.
话虽这么说,在这种情况下触发编译器错误的更好方法是简单地使用静态断言:static_assert(p_[0]!='a', "String does not begin with 'a'.")
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)