【发布时间】:2021-02-19 12:09:41
【问题描述】:
我正在向自己介绍 C++,可悲的是,对于动态创建的固定大小数组(但大小仅在运行时已知)的支持似乎在 C++ 中非常差,因为 new[] 可以t 使用用户设置的参数调用任意用户指定的构造函数。
考虑class A,它有许多构造函数,每个构造函数都有一些参数。假设没有参数的构造函数是无用的(如果我基本上不需要它,我不想写一个)。我想以下内容无关紧要,但是,以防万一:假设A 仅包含一个可能很大的std::vector<Internal>(Internal 是一个私有类,T 和S 参数化A)和就数据成员而言,是一个整数计数器。另外,A 是参数化的。
假设我们希望A 的n 实例作为数组连续存储在内存中,其中n 在运行时确定并在之后保持不变。我们希望能够通过将参数传递给A 或类似的构造函数的单个调用来创建和初始化结构。所以数组中的每个实例都得到相同的,但程序化的初始化。编辑:对不起,我并不是说我想要 O(1) 初始化,因为那是不可能的,我只想要 O(n) 初始化,但是这样我就可以在一个语句中创建数组。即,这样我就不必为我创建的每个数组编写一个初始化循环。
std::vector<A<T,S>> 是一个可能但不是最佳的解决方案,但假设我们不能忍受低效率。 (请记住,std::vector 支持调整大小。)
如何实现和/或使用具有良好 API 的高效解决方案?
我更喜欢不重新实现一半标准库的解决方案,即考虑 C++20 功能和可用于实现的标准库。另外,不要让我违反 C++ 别名 rules。
一个可能相关的问题是为什么标准库中缺少这样一个“fixed_size_vector”类?
(顺便说一句:没关系,但请不要说“只使用向量”,因为在这种情况下,我确实会采用提到的次优解决方案,因为性能对我的玩具程序并不重要,但在现实世界中,性能有一天会很重要,我想做好准备。编辑:我确实不是的意思是我想优化我的玩具程序,而是我指的是有一天我将不得不优化其他一些程序。)
编辑:回答一些评论者:包装 std::vector 可以提供正确的抽象,但它会不必要地低效。一条评论链接了一个问题,其最佳答案很好地解释了这一点:
dynarray 比 vector 更小更简单,因为它不需要 管理单独的大小和容量值,并且不需要 存储分配器
(dynarray 这里是对 stdlib 的提议添加,这似乎是我想要的,除了它还应该依赖特殊的编译器支持来支持它的某些语义)。当然,与 std::vector 相比,这种差异在大多数情况下并不重要,但如果我能够简单地使用正确的工具来完成这项工作,那仍然是一件好事。
【问题讨论】:
-
只需使用
std::vector(即使您说不这样做 - 它也有效)。 -
请不要说“只使用矢量” 但这就是解决方案。它具有您想要/需要的所有界面。如果您唯一关心的是有人可以扩展向量,那么将
vector包装在您自己的类中,并且不要提供任何可能增加向量大小的函数。您也可以只创建一个const vector<YourType>并使用您想要的所有对象构建它。向量中的对象不会是const,但由于向量是,如果您尝试更改向量本身的状态,则会收到错误消息。 -
“在现实世界中,性能总有一天会很重要,我想做好准备” 你绝对会想要放弃这种心态。现实世界的代码首先是关于可维护性和可伸缩性的。你不是为电脑编程,你是为人编程。优化对瓶颈和明显的清理很重要;但是,如果您尝试对所有内容进行微优化,那么您作为 C++ 开发人员的职业生涯将不会很长
-
关于您的编辑:您似乎不明白效率到底是什么以及它与
std::vector的关系。您可以预先在向量中保留空间,这相当于为n对象分配存储空间在调用构造函数之前。我建议你真正了解std::vector的能力及其工作原理,而不是忽视正确答案 -
"但假设我们不能忍受低效率。(记住 std::vector 支持调整大小。)";如果你不使用它,你就不用付钱。
标签: c++ arrays templates constructor c++20