1
#include <stdio.h>
#include <iostream>
#include <string>


using namespace std;

class myClass{

public:
    int *num1;
    myClass();


};

myClass::myClass(){
    num1 = new int[1];
    num1[0] = 10;
}


int main()
{
    myClass *myclass;

    myclass = new myClass[10];

    cout << myclass[0].num1[0] << endl;

    delete &myclass[0];
    cout << myclass[0].num1[0] << endl;

}

我想删除 myclass 的第一个实例(myclass[0])。

此代码运行不正确,在删除部分失败。我可能缺少一些东西。

我做错什么了?

4

2 回答 2

2

您不能只删除使用创建的数组的一部分newnew分配一块只能一起delete编辑的内存块。

如果你想让一个对象释放它自己的内部数据,你必须安排这个应该封装和隐藏它自己的内部资源的类来自己做。

如果您想要一个较小的内存块来保存您分配的数组,那么您必须分配一个较小的块并将您希望保留的内容移动到新块中,然后删除整个旧块:

int *arr = new int[10];

int *tmp = new int[9];
std::copy(arr+1, arr+10, tmp);
delete [] arr;
arr = tmp;

你需要设计你的类来管理它自己的资源,并处理复制或移动。您的 currentmyClass分配了一个数组,但依赖于其他代码来处理清理。这不是做这件事的好方法,因为通常没有其他代码可以做正确的事情,即使你可以,你也会经常犯错误。

由于您在构造函数中进行分配,因此您需要一个处理释放的析构函数。然后,由于您实现了三个特殊操作之一(copy-ctor、copy-assignment、析构函数),您需要考虑全部实现它们。(这被称为“三法则”。在 C++11 中,它变成了“五法则”,并添加了 move-ctors 和 move assignment。)

class myClass {
public:
    myClass();

    // destructor to handle destroying internal resources correctly
    ~myClass();

    // copy constructor and copy assignment operator, to handle copying correctly
    myClass(myClass const &rhs);
    myClass &operator=(myClass const &rhs);

    // move constructor and move assignment operator, to handle moves correctly (C++11)
    myClass(myClass && rhs);
    myClass &operator= (myClass &&rhs);

private:
   int *num1; // private so external code can't screw it up

public:
   // limited access to num1
   int size() const { if (num1) return 1; else return 0; }
   int &operator[] (size_t i) { return num1[i]; }
};

您可以像以前一样实现构造函数,也可以使用初始化列表和 C++11 统一初始化:

myClass::myClass() : num1(new int[1]{10}) {}

现在,您想要的析构函数取决于您希望类具有的语义以及您想要维护的特定不变量。“值”语义是 C++ 中的规范(如果您熟悉 Java 或 C#,这些语言鼓励或要求用户定义类型的“参考”语义)。如果您想要值语义,并且如果您维护一个 num1 始终拥有内存或为空的不变量,则可以使用下面的析构函数。

myClass::~myClass() { delete num1; }

可以以不同的方式处理复制和移动。如果你想完全禁止它们,你可以说(在 C++11 中):

myClass::myClass(myClass const &rhs) = delete;
myClass &myClass::operator=(myClass const &rhs) = delete;

myClass::myClass(myClass && rhs) = delete;
myClass &myClass::operator= (myClass &&rhs) = delete;

或者,如果您想允许复制和/或移动(并保持值语义和上面提到的不变量),那么您可以实现这对函数中的一个或两个:

myClass::myClass(myClass const &rhs) : num1( rhs.size() ? new int[1]{rhs[0]} : nullptr) {}
myClass &myClass::operator=(myClass const &rhs) {
    if (num1)
        num1[0] = rhs[0];
}

myClass::myClass(myClass && rhs) : num1(rhs.num1) { rhs.num1 = nullptr; } // remember to maintain the invariant that num1 owns the thing it points at, and since raw pointers don't handle shared ownership only one thing can own the int, and therefore only one myClass may point at it. rhs.num1 must be made to point at something else...
myClass &myClass::operator= (myClass &&rhs) { std::swap(num1, rhs.num1); } // steal rhs.num1 and leave it to rhs to destroy our own num1 if necessary. We could also destroy it ourselves if we wanted to.

有了这个实现,您现在可以像对待int任何其他“值”类型一样对待 myClass 对象。您不再需要担心管理其内部资源;它会自己照顾他们。

int main() {
    std::vector<myClass> myclassvec(10);

    cout << myclassvec[0][0] << '\n';

    myclassvec.erase(myclassvec.begin()); // erase the first element

    cout << myclassvec[0][0] << '\n'; // access the new first element (previously the second element);
}
于 2012-11-18T07:46:52.710 回答
1

在您的类中创建一个函数来处理其私有成员的删除,可能称为FreeMem(int index)

void myClass::FreeMem()
{
    delete [] num1
}

但老实说,在这类程序中不使用析构函数就释放对象的内存是危险的,而且是非常糟糕的做法。我建议释放析构函数中的内存,因此当对象终止时,它会释放内存,

myClass::~myClass()
{
    delete [] num1;
}

需要注意的另一件事是,如果您只在动态变量中创建一个值,则将其写为:

int * pnum = new int;
//or in your class..
pnum = new int;

除其他外,您的程序中有很多缺陷。我建议重新阅读课程。

于 2012-11-18T06:05:10.823 回答