无限数组C++在一个表达式中使用两个新值调整数组大小
Infinite array C++ resizing the array with two new values in one expression
我已经开始使用C++中的模板实现无限数组。除了在一个表达式中添加两个新项的特殊情况外,添加整数效果很好,这需要一个接一个地调整两个大小(参见下文)。
#include <iostream>
#include <cstddef>
#include <new>
#include <string.h>
template <typename T>
struct infinite_array {
infinite_array();
auto operator[](unsigned long long idx) -> T&;
auto size() const -> unsigned long long;
void resize(unsigned long long idx);
private:
T *data;
unsigned long long array_length;
};
template <typename T>
void infinite_array<T>::resize(unsigned long long idx)
{
std::cout << "Resize with idx " << idx << std::endl;
T* temp = new T[idx];
memset(temp, 0, sizeof(T) * idx);
for (int i = 0; i < array_length; ++i) {
temp[i] = data[i];
std::cout << temp[i] << " ";
}
std::cout << std::endl;
//std::copy(data, data+size(), temp);
delete [] data;
data = temp;
array_length = idx;
}
template <typename T>
infinite_array<T>::infinite_array()
{
data = NULL;
array_length = 0;
}
template <typename T>
auto infinite_array<T>::size() const -> unsigned long long {
//array_length = sizeof(data)/sizeof(T);
return array_length;
}
template <typename T>
auto infinite_array<T>::operator[](unsigned long long idx) -> T& {
//std::cout << "Accessing element at idx " << idx << std::endl;
if (idx+1 > size()) {
resize(idx+1);
}
return data[idx];
}
int main() {
infinite_array<int> ar;
for (int i = 0; i < 10; ++i) {
ar[i] = i;
}
// PROBLEM: ONLY ar[31] is initialized successfully to 10
ar[30] = ar[31] = 10;
for (int i = 0; i < ar.size(); ++i)
std::cout << ar[i] << ' ';
std::cout << std::endl;
return 0;
}
恐怕没有办法解决您的问题,因为您无法控制对operator[]
的调用顺序。这就是问题所在:
-
编译器选择首先评估
ar[30]
,这将调整数组的大小并返回对其一个元素的引用。 -
之后,对
ar[31]
进行求值,再次调整数组的大小,返回对新数组元素之一的另一个引用旧引用仍然指向旧数组中的元素(已删除!)。 -
最后,编译器执行赋值,为两个元素分配10。但是,由于其中一个元素位于已删除的旧数组中,因此在新数组中看不到它。
简单的事实是,不能像这样将调用链接到operator[]
,不能绕过编译器可以按任何顺序执行调用的事实。
此外:逐个调整缓冲区的大小通常是个坏主意,其复杂性是二次型的。典型的代码使用至少因子2的增量。精确的因子并不那么相关,相关的是你使用了一个因子,因为这样你就把复杂性降到了O(n)。值2只是空间和时间开销之间的一个很好的折衷。
通常,您不希望让您的访问器方法(at()
或operator[]
)调整数组的大小,因为这会违反关注点的分离(每个函数应该做1件事-调整大小需要做2件事)。
标准库实现std::vector
的方式:如果您使用at()
并提供一个越界地址,它将抛出一个异常(如果使用operator[]
,则为UB)。
遇到的问题
ar[30] = ar[31] = 10;
如果必须调整数组的大小,那么两个调用都必须调整它的大小。这与i = i++ + ++i;
(也是UB)的情况非常相似。当您将大小调整为31时,您有一个临时缓冲区,并将新元素的值设置为10。当您将大小调整为32时,您有一个(不同的)临时缓冲区,并将新元素的值设置为10。当后一个返回时,它没有前一个的值,所以只写1。要解决此问题,请分开操作。
- 如何在C++初始化时更改数组的值?
- 遇到此问题时遇到困难:允许用户输入数组的值并使用 for,而循环也输出输入的最大数字
- 数组初始值设定项的构造函数歧义
- 我们可以将集合的值存储在变量中吗?就像我们可以将数组的值存储在变量中一样
- 我正在尝试解决一个需要数组总和值但代码不起作用的问题,我想做这样的事情
- C++:数组<>初始值设定项太多
- 查找数组中指示性较大但数组中值较小的元素
- 在 Arduino 中为 2D 指针数组赋值
- C++ "oldstyle container ":指针/数组/新 - 可能误会?
- 我无法为 2D 数组赋值
- 如何在C++中初始化值,然后稍后为uint32_t数组赋值
- 尝试设置唯一指针布尔数组的值时BAD_ACCESS错误
- 使用指针显示数组的值
- 使用指针访问数组的值
- 向对象数组 c++ 添加值
- 返回数组中值的指针地址
- 如何在给定的间隔内更改数组的值
- 如何更改数组的值然后显示整个新数组
- 将数组的值传递给修改值的函数,然后将其返回到新数组中
- 删除现有指针数组的值,然后为指针数组分配新值