c++ - 在 C++ 中手动调整数组大小
问题描述
如果之前已经介绍过,我很抱歉。我知道如何做到这一点是 C 和 Java,但不是 C++。如果不使用包含 Vector 使用的预先存在的类,您将如何根据下面的代码增加数组的大小?
数组扩展和对数组的赋值发生在 push() 中,注释全部大写。
编辑:正如我在下面的评论中提到的,这是一个关于手动重新分配数组而不是使用 std::vector 或“动态数组”的问题。
线.h
#include <iostream>
#include "Point.h"
using namespace std;
class Line {
public:
Line();
virtual ~Line();
// TAKE IN NEW POINT, INCREASE THE ARRAY SIZE AND ADD NEW POINT TO THE END OF THE ARRAY
void push(const Point& p);
private:
unsigned int index; // size of "points" array
Point* points;
};
主文件
#include <iostream>
#include "Point.h"
#include "Line.h"
using namespace std;
int main() {
int x, y;
int size; // Some user defined size for the array
Line line;
Point a[size]; // Some points that are already filled
// Push the data in a[] to the variable "line"
for(int i = 0; i < size; i++){
// Increase array size of Point* points in variable line and add a[i] to the end of the array
line.push(points[i]);
}
return 0;
}
解决方案
简单的答案是在这种情况下您应该始终使用 std::vector 。但是,解释为什么会这样可能会很有用。因此,让我们考虑一下如何在没有 std::vector 的情况下实现它,这样您可能会明白为什么要使用 std::vector:
// Naive approach
Line::push(const Point& p)
{
Point* new_points = new Points[index + 1];
std::copy(std::make_move_iterator(points), std::make_move_iterator(points+index), new_points);
new_points[index] = p;
delete[] points;
points = new_points;
index += 1;
}
这种方法有很多问题。每次插入条目时,我们都被迫重新分配和移动整个数组。然而,一个向量会预先分配一个预留空间,并为每个插入使用预留空间,只有在超过预留限制时才会重新分配空间。这个平均向量在性能方面将远远超过您的代码,因为更少的时间将花费在不必要的分配和移动数据上。接下来是异常问题,此实现没有异常保证,因为 std::vector 为您提供了强大的异常保证:https ://en.wikipedia.org/wiki/Exception_safety 。为您的类实现强大的异常保证并非易事,但是如果您按照 std::vector 这样的方式实现它,您将自动得到它
Line::push(const Point& p)
{
points.push_back(p);
}
您的方法还有其他更微妙的问题,您的类没有定义复制或赋值运算符,因此会生成编译器生成的浅拷贝版本,这意味着如果有人复制您的类,那么分配的成员将被删除两次。要解决此问题,您需要遵循 C++11 之前的 3 范式规则和 C++ 11 以后的 5 规则:https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)。但是,如果您使用了向量,则不需要这些,因为您将从零规则中受益并能够依赖编译器生成的默认值:https ://blog.rmf.io/cxx11/rule-of-zero