1

考虑下面的示例代码。该类Data用于存储数据数组:为简单起见,我选择使用 avector<char>作为数据成员。但是,这些数据必须由外部例程处理,这需要一个指向数组第一个元素的指针,当然还有这个数组的长度:为此,我还实现了函数get_data()get_length().

class Data
{
public:
    Data(const char* sourcePtr, int sourceLength) : _data(sourcePtr, sourcePtr+sourceLength) { ; }

    const char* get_data() const { return &_data.front(); }
    int get_length() const { return _data.size(); }

    void print() const
    {
        vector<char>::const_iterator it;
        for(it = _data.begin(); it != _data.end(); ++it)
            cout << *it;
    }

private:
    vector<char> _data;
};

现在考虑以下使用类的代码示例Data

int main(int argc, char** argv)
{
    char* a = new char[4];
    a[0] = 'b';
    a[1] = 'y';
    a[2] = 't';
    a[3] = 'e';

    Data myData(a,4);
    delete[] a;

    myData.print();
    cout << endl;

    const char* aPtr = myData.get_data();

    // The following statement frees the memory allocated
    // for the data member of the class Data.
    delete[] aPtr;

    return 0;
}

上面的语句delete[] aPtr释放了为类的数据成员分配的内存Data。结果,当myData对象被自动解除分配时, 的内容vector<char>已经被手动解除分配,显然会出现错误SIGABRT

如何确保编译器将该语句表示delete[] aPtr为错误?你应该如何修改类Data来实现这个目标?

4

4 回答 4

6

处理这个问题的最直接的方法是确保清楚谁是指针的“所有者”。在我的 C++ 时代,如果一个函数返回了一个指针,那么函数的名称应该以“Create”而不是“Get”开头。后来,我们通常在这种情况下返回智能指针。

事实上,编写 C++ 一点也不难,你永远不需要显式删除任何指针,而是将所有指针存储在一个智能指针中,当指针被销​​毁时它会删除它。

于 2013-03-05T21:38:52.317 回答
4

停止使用“裸”newdelete操作,将其包装new在 RAII 类型中并且不要使用delete,除非您正在编写 RAII 类型的析构函数。

std::unique_ptr<char[]> a{ new char[4] };
a[0] = 'b';
a[1] = 'y';
a[2] = 't';
a[3] = 'e';

Data myData(std::move(a),4);

这段代码意味着数组的所有权明确地赋予了智能指针,然后明确地转移给了Data对象。尝试delete该数组将无法编译。

这并不会阻止用户以后这样做delete[] aPtr,但是如果您养成了从不使用RAII 类型的析构函数中除外的习惯,那么当有人通过使用他们不应该使用的地方引入错误时delete,就会变得非常delete明显,因为他们没有拥有记忆。

停止摆弄裸指针。如果您的代码的用户不会停止这样做,那么让他们以艰难的方式学习。

于 2013-03-05T22:00:53.420 回答
1

你没有。 new并且delete不要跟踪谁拥有指针。那是你的工作。

相反,您可以做的是复制指针指向的数据。然后调用者对其数组做了什么并不重要。你有自己的副本,假设你没有做一些脑残的事情,比如把它暴露给任何想要它的人,它是安全的。

或者,查看std::unique_ptrstd::shared_ptr。:P 就内存管理而言,它们是新的热点;当您使用智能指针时,内存几乎可以自行管理。

于 2013-03-05T21:36:14.033 回答
1

写好文档。阻止其他程序员做愚蠢的事情不是你的工作。

于 2013-03-05T21:51:27.303 回答