首页 > 解决方案 > 在 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;
}

标签: c++c++11

解决方案


简单的答案是在这种情况下您应该始终使用 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


推荐阅读