【问题标题】:C++ how to add an element to a pointer array by exceeding sizeC ++如何通过超出大小将元素添加到指针数组
【发布时间】:2020-03-13 22:33:43
【问题描述】:

假设我们创建了动态分配的内存,例如:

int SIZE = 10;
int *p = new int[SIZE];
for(int i = 0; i < SIZE; ++i)
  p[i] = i;

它会将 0 到 9 分配给我们的指针数组。
然后我想将 10,11,12 添加到数组中
我能做到吗:

p[10] = 10;
p[11] = 11;
p[12] = 12;

或者我应该这样做:

delete[] p;
size = 13;
p = new int[SIZE];
for(int i = 0; i < SIZE; ++i)
  p[i] = i;

【问题讨论】:

  • 既然是C++,为什么不直接用vector&lt;int&gt;呢?
  • 这几乎没有帮助。我认为如果问题涉及使用数组,那么该建议作为“也......”的侧面答案很好,但这个问题非常具体地与动态数组有关。 SO 现在正在赢得它的刻板印象。
  • 要调整数组的大小,您必须分配一个新数组并将旧元素复制到新数组,然后删除旧数组。 stackoverflow.com/questions/42238712/change-array-size-c
  • @sweenish -- 评论部分适用于 cmets,而不是答案。我认为评论为什么不使用 vector 没有任何问题。
  • @machine_1 - 仅当内存已使用 malloc()calloc()realloc() 分配时。但是由于各种原因,在 C++ 中不鼓励使用这些函数(来自 C) - 特别是,它给出了未定义的行为,用于为具有非平凡构造函数或析构函数的 C++ 类类型分配内存。

标签: c++ arrays pointers vector memory-management


【解决方案1】:

您必须为更大的数组重新分配内存。否则程序将有未定义的行为。

例如

int SIZE = 10;
int *p = new int[SIZE];
for(int i = 0; i < SIZE; ++i)
  p[i] = i;

int *tmp = new int[SIZE + 3];

std::copy( p, p + SIZE, tmp );
delete []p;
p = tmp;

p[SIZE++] = 10;
p[SIZE++] = 11;
p[SIZE++] = 12;

或者你可以写出最后三个语句来代替

for ( const int &value : { 10, 11, 12 } ) p[SIZE++] = value;

当然在这种情况下最好使用标准容器std::vector

其实上面的代码和下面的差不多

#include <vector>

//...

std::vector<int> v( 10 );

for ( int i = 0; i < v.size(); i++ ) v[i] = i;

v.reserve( 13 );
for ( const int &value : { 10, 11, 12 } ) v.push_back( value );

除了所有的内存管理都由向量内部完成。

【讨论】:

  • p[SIZE++]时厌恶地摇晃是不是不对?
  • 因为无论如何我们都在删除旧数组,所以我更喜欢std::move 而不是std::copy - 虽然与整数无关,但它可能对复杂类型(如std::string)产生很大影响。 ..
  • @Aconcagua 我同意你的看法。
  • 嗯,不一定等效,构造函数可能决定从一开始就保留更多元素,在这种情况下可能不会发生重新分配。并且std::vector 移动,如果可能的话......
【解决方案2】:

第二个选项是正确的方法。第一个选项不会总是抱怨,但是您正在写入尚未为数组预留的内存;它已被留作其他用途,而您不知道是什么。有时它会表现得很好,有时它不会。分配给超出其范围的数组是未定义的行为,我们应该避免它。

【讨论】:

  • 第二个选项是错误的,因为它混合了sizeSIZE
  • 我将其归结为一个简单的错字,但最好提出来。
【解决方案3】:

在您的第一个示例建议中:

p[10] = 10;
p[11] = 11;
p[12] = 12;

您将覆盖不属于您的内存,这可能会导致崩溃。您需要重新分配原始数组。

const int oldSize = SIZE;
SIZE = 13;
int *newP = new int[SIZE];
memcpy(newP, p, oldSize * sizeof(int));
for (int i = oldSize; i < SIZE; ++i)
{
    newP[i] = i;
}

delete[] p;
p = newP;

您的第二个示例可以工作,但效率稍低,因为您在每次重新分配时都重新计算值。在我上面的示例中,您只需重新计算新值。

或者,您应该查看专门为此目的设计的std::vector(动态调整大小的数组)。

std::vector<int> p;
for (int i = 0; i < 10; ++i)
{
    p.push_back(i);
}

这里std::vector 在内部管理分配,因此您不必担心newdelete

【讨论】:

  • 旁注:如果涉及复杂对象(如std::string),memcpy 通常是无效的。为了保持一致性,我会避免使用 memcpy,即使是实际上允许使用 C++ 的类型,例如 std::copy
  • 是的,我同意,我回答的初衷是保留问题的“风格”(即原始指针和手动内存管理),但是是的,应该不鼓励使用 memcpy。
猜你喜欢
  • 1970-01-01
  • 2015-09-09
  • 1970-01-01
  • 1970-01-01
  • 2010-10-19
  • 2018-04-10
  • 1970-01-01
  • 1970-01-01
  • 2018-11-26
相关资源
最近更新 更多