当对象包含指针成员时,堆栈上对象破坏的段错误?
Segfault on object destruction on the stack when object containing pointer member?
下面的场景看起来很令人费解(这不是一个工作代码,只是一个非常简化的版本来说明这个场景,你明白了):
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 等对象的 class 定义如下所示时,您永远不能再在堆栈上分配此类对象?或者,我只是简单地不为 A 定义析构函数,然后 A 和 B 都可以分配到堆栈上 --- 但这可能很糟糕并且可能会导致内存泄漏? (如果有一天其他人看了代码并决定使用新的 A)。
我认为 C++ 相对于 Java 的主要优势是你可以避免 new 并始终处理堆栈上的对象以加快速度,但是在堆栈或堆上使用对象的这种不灵活性又如何呢,喜欢吗?
C++ 有什么问题?那么下面两种方式应该走哪一种呢?
如上定义classA,A和B总是new,以后记得只删除A。
定义没有析构函数的 class A,然后始终在堆栈上创建 A 和 B 并按值传递对象(但是在某些情况下我不想要 public 拷贝构造函数).
你假设这个段错误是正确的,因为你正在删除一个在堆栈上分配的项目。您只能删除分配给新的项目。此外,在同一代码层内分配和释放内存被认为是一种很好的做法。如果您必须在代码中使用对象 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; }
}
}
Which of the following two ways should one go then?
都没有。使用选项 3:根本不要这样做。你是对的,C++ 的一个优点是你不需要 new
和 delete
,但是你写了一大堆使用 new
和 delete
的代码.
你想用这个 A
解决什么问题?毫无疑问,有比 A
.
更好的方法来解决问题
下面的场景看起来很令人费解(这不是一个工作代码,只是一个非常简化的版本来说明这个场景,你明白了):
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 等对象的 class 定义如下所示时,您永远不能再在堆栈上分配此类对象?或者,我只是简单地不为 A 定义析构函数,然后 A 和 B 都可以分配到堆栈上 --- 但这可能很糟糕并且可能会导致内存泄漏? (如果有一天其他人看了代码并决定使用新的 A)。
我认为 C++ 相对于 Java 的主要优势是你可以避免 new 并始终处理堆栈上的对象以加快速度,但是在堆栈或堆上使用对象的这种不灵活性又如何呢,喜欢吗?
C++ 有什么问题?那么下面两种方式应该走哪一种呢?
如上定义classA,A和B总是new,以后记得只删除A。
定义没有析构函数的 class A,然后始终在堆栈上创建 A 和 B 并按值传递对象(但是在某些情况下我不想要 public 拷贝构造函数).
你假设这个段错误是正确的,因为你正在删除一个在堆栈上分配的项目。您只能删除分配给新的项目。此外,在同一代码层内分配和释放内存被认为是一种很好的做法。如果您必须在代码中使用对象 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; }
}
}
Which of the following two ways should one go then?
都没有。使用选项 3:根本不要这样做。你是对的,C++ 的一个优点是你不需要 new
和 delete
,但是你写了一大堆使用 new
和 delete
的代码.
你想用这个 A
解决什么问题?毫无疑问,有比 A
.