重新初始化指针是一种不好的做法吗?

3

我有一个Image类,最初我不知道图像的尺寸,所以我只是将data_指针初始化为大小为0的数组。稍后当我找到图像信息时,我会重新初始化data_为新的大小。这样做会在内存上创建任何问题吗?是否有更简洁的方法来实现这个目标?

下面是我编写的类:

class Image
{
private:
    int numRows_, numCols_;
    unsigned char* data_;
public:
    Image() : numRows_(0), numCols_(0), data_(new unsigned char[0])
    {}
    void setData(int r, int c, unsigned char* data)
    {
        this->numRows_ = r;
        this->numCols_ = c;
        this->data_ = new unsigned char[r*c];
        for (int i = 0; i < r*c; i++)
        {
            this->data_[i] = data[i];
        }
    }
    int rows();
    int cols();
    unsigned char* data();
    ~Image();
};

感谢您的提前帮助。

5
直接将其设置为nullptr有什么不可取的理由吗? - Rotem
4
无法重新初始化东西。初始化仅执行一次。之后的任何操作都只是赋值。 - Algirdas Preidžius
3
setData中,如果data_已经被初始化并指向其他数据,会怎样? - Some programmer dude
1
为什么在你不知道要放入什么数据之前就创建对象呢?如果你只是在知道信息后再创建它,那么你可以避免其他评论中提到的问题。 - doctorlove
4
std::vector 是一个 C++ 标准库中的容器,它可以动态调整大小,存储任意类型的对象,并支持随机访问。 - Lightness Races in Orbit
显示剩余5条评论
2个回答

7
这实际上会泄漏内存。调用new为数组分配内存,即使它是空的(链接1)。一旦重新分配data_,先前的数组就会泄漏并且不能再被释放。
您可以确保delete[]您分配的任何new[],或者只是不分配空数组,而是将data_设置为nullptr,直到您有有意义的数据可用为止。
更好的想法是不允许在无效状态下创建对象,要求在构造函数中提供数据-请参见RAII

在RAII中,持有资源是类不变量,并与对象生命周期相关:资源分配(或获取)在对象创建(特别是初始化)期间由构造函数执行,而资源释放则在对象销毁(特别是终结)期间由析构函数执行。

如果您决定保留setData,那么如评论中所提到的,您还必须确保在重新分配data_之前delete[] setData中的现有数据,以防该方法被调用多次。

谢谢@Rotem,这次我将使用nullptr,但出于好奇,是否明智地使用其中一个公共方法调用delete[]来删除私有指针data_?我有一种感觉,如果可能的话应该避免这样做。 - Ijlal
@Ijlal 为什么?那会引入什么样的危险? - Rotem

3

我认为更加简洁的实现方式是使用向量:

std::vector<unsigned  char> v; // vector with size 0
v.resize(r*c);                 // after size is known, just resize

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接