以下场景似乎非常令人困惑(这不是一个工作代码,只是一个非常简化的版本来说明该场景,你明白了):
class A {
private:
B* mb;
public:
A(B *b):mb(b) {}
~A() {
if(NULL != mb) { delete mb; }
}
}
int main(int argc, char **argv) {
B* b = new B();
A* a = new A(b);
delete A; //Everything is fine here
B b;
A* a = new A(&b);
//This will segfault, because b is allocated on the stack?
delete A;
B b;
//This segfaults as well because when it goes out of scope
//the program tries to delete b twice?
A a(&b);
}
如果我正确理解这一点,这是否意味着当它们的类定义看起来像这样时,你再也不能在堆栈上分配像A和B这样的对象了?或者,我只是不为a定义析构函数,然后a和B都可以在堆栈上分配——但这可能很糟糕,可能会导致内存泄漏?(如果有一天其他人查看了代码并决定使用新的A)。
我认为C++相对于Java的主要优势是可以避免新的对象,并始终处理堆栈上的对象以加快速度,但像这样在堆栈或堆上使用对象的灵活性又如何呢?
C++有什么用?那么,以下两种方式中的哪一种应该走呢?
如上定义类A,并始终新建A和B,而以后请记住仅删除A。
定义不带析构函数的类A,然后总是在堆栈上创建A和B,并按值传递对象(但在某些情况下,我不想要公共复制构造函数)。
您假设这个segfault是正确的,因为您正在删除在堆栈上分配的项。您只能删除已用new分配的项目。此外,在同一层代码中分配和释放内存也是一种很好的做法。如果您必须在代码中使用对象B,最好创建B:的副本
class A {
private B* mb;
public:
A(B *b) {
mb = new B(*b); // calls B's copy constructor
}
~A() {
if(NULL != mb) { delete mb; }
}
}
那么应该采用以下两种方式中的哪一种?
两者都没有。使用选项3:根本不要这样做。你说得对,C++的一个优点是你不需要new
和delete
,但你写了一大堆使用new
和delete
的代码。
你想用这个A
解决什么问题?毫无疑问,有比A
更好的方法来解决这个问题。