通过 constexpr 初始化数组
Posted
技术标签:
【中文标题】通过 constexpr 初始化数组【英文标题】:Array initialization by constexpr 【发布时间】:2016-06-08 21:47:45 【问题描述】:为什么从constexpr
初始化array
的维度如此重要?下面代码中的常规variable
是否暗示(如果允许合法)将来可能是array
的resizing
?
int a=5;
int arr[a];
a=10;
【问题讨论】:
C99 添加了对此的支持,称为可变长度数组,或 VLA。它们不太适合 C++ 类型系统。特别是,sizeof
始终是 C++ 中的编译时间。
你认为arr
的类型是什么?请注意,在编译时必须知道类型,并且还要注意数组的大小是其类型的一部分。
数组大小是类型的一部分。所以看到int[a]
的每个人都必须看到相同的类型。想象一下你有using T = int[a];
。如果a
可以改变,那意味着什么?
C++ 已经有一个标准化的可移植变长数组,它被称为std::vector
。 vector
和 VLA 之间的唯一区别是 vector
在堆上分配其数组,而 VLA 在堆栈上分配其数组(在堆栈上分配可变长度数据是危险的,这就是为什么 @ 987654335@ 从未标准化)。 VLA 是针对那些想要支持它的供应商特定的编译器扩展。
@M.Pak 否。在一般情况下,编译器无法知道非常量变量的值。所以它不会试图在这样的特定情况下弄清楚。您需要一个常量(字面量)、const 或 constexpr。
【参考方案1】:
n3497 提出了这样的功能,但在 C++14 之前被废弃。 C 和 C++ 是完全不同的语言。它们的语法可能相似,但它们的演变却大相径庭。 C++ 旨在成为更安全的类型,并去除危险或无用的特性(如 auto_ptr
)。
C++“VLA”无论如何都不是很有用,举几个明确排除在提案中的特性:
多维数组,除了顶层之外还有运行时绑定(类似地,array-new 也不支持) 对函数声明语法的修改 sizeof(a) 是一个运行时评估的表达式,返回 a 的大小 "typedef int a[n];"评估“n”并将其传递给 typedef
毫无疑问还有更多的情况。 C++ 的规范是 C99 的两倍,然后一些,想象一下“为什么这个 Quirk 有效”或“为什么这个 Quirk 不起作用”或“这个 Quirk 合法吗?”的大量错误报告。因为到处都有人试图硬塞 VLA。
该论文甚至对 VLA 提出了普遍的批评:
堆栈溢出变得更有可能,特别是如果大小取决于 在外部输入上,并没有正确检查。有些环境可能 因此禁止使用该功能。这样的禁令可以 使用静态分析工具轻松实施。
想象一下,如果这是一项功能,将会编写多少粗心的废话。您可能会争辩说,在 C++ 中,您可能会自责。但 C++ 至少会尝试调整您的视线,以便撞击点是地板而不是您的脚。
你应该怎么做?
使用std::vector
。对简单程序的性能有抱怨吗?你过早地优化了。
【讨论】:
以上是关于通过 constexpr 初始化数组的主要内容,如果未能解决你的问题,请参考以下文章
如何编写工厂函数来初始化 C++ 中的 constexpr 引用?
使用 constexpr 成员函数初始化 constexpr 成员变量
为啥我不能使用 constexpr 全局变量来初始化 constexpr 引用类型?