C++ 当对象包含指针成员时,堆栈上的对象销毁出现Segfault?

C++ 当对象包含指针成员时,堆栈上的对象销毁出现Segfault?,c++,segmentation-fault,heap-memory,destructor,stack-memory,C++,Segmentation Fault,Heap Memory,Destructor,Stack Memory,下面的场景看起来非常复杂(这不是一个工作代码,只是一个非常简化的版本来说明场景,您明白了): 如果我理解正确的话,这是否意味着当类定义看起来像这样时,就再也不能在堆栈上分配像A和B这样的对象了?或者,我只是不为a定义析构函数,然后a和B都可以在堆栈上分配——但这可能是不好的,并且可能会导致内存泄漏?(如果有一天其他人查看代码并决定使用新代码) 我认为C++在java上的主要优点是可以避免新的和总是处理堆栈上的对象来加速,但是在堆栈或堆上使用对象的灵活性是什么呢? < C++中的交易是什么?那么,

下面的场景看起来非常复杂(这不是一个工作代码,只是一个非常简化的版本来说明场景,您明白了):

如果我理解正确的话,这是否意味着当类定义看起来像这样时,就再也不能在堆栈上分配像A和B这样的对象了?或者,我只是不为a定义析构函数,然后a和B都可以在堆栈上分配——但这可能是不好的,并且可能会导致内存泄漏?(如果有一天其他人查看代码并决定使用新代码)

<>我认为C++在java上的主要优点是可以避免新的和总是处理堆栈上的对象来加速,但是在堆栈或堆上使用对象的灵活性是什么呢? < C++中的交易是什么?那么,应该选择以下两种方式中的哪一种

  • 如上所述定义类A,并且始终是新的A和B,而以后记住只删除A

  • 定义不带析构函数的类A,然后始终在堆栈上创建A和B,并按值传递对象(但在某些情况下,我不需要公共副本构造函数)


  • 假设此错误是正确的,因为您正在删除在堆栈上分配的项。您只能删除已分配了新资源的项目。此外,在同一层代码中分配和释放内存被认为是一种良好的做法。如果必须在代码中使用对象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; }
        }
    }
    

    假设此错误是正确的,因为您正在删除在堆栈上分配的项。您只能删除已分配了新资源的项目。此外,在同一层代码中分配和释放内存被认为是一种良好的做法。如果必须在代码中使用对象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++的优点是不需要代码>新< /COD>和<代码>删除<代码>,但是你编写了一组代码,使用了<代码>新< /COD>和<代码>删除< /> > 您想用这个
    A
    解决什么问题?毫无疑问,有比使用
    a
    更好的方法来解决这个问题

    那么,应该选择以下两种方式中的哪一种

    都不是。使用选项3:根本不要这样做。没错,C++的优点是不需要代码>新< /COD>和<代码>删除<代码>,但是你编写了一组代码,使用了<代码>新< /COD>和<代码>删除< /> >

    您想用这个
    A
    解决什么问题?毫无疑问,有一个更好的解决问题的方法比<<代码> < <代码> > < /p>代码不是C++。它没有编译。这不是完整的代码,只是一个简单的例子来说明…@Superziyi,这没有帮助。请发布可以编译的代码。原始代码很大…但是要从零开始获得精简版本,我必须创建适合场景的新类。然而,这个例子本身不是不言自明的吗?我不知道发布的每个代码片段都需要能够编译,如果是这样的话,请告诉我。谢谢你!“这个例子本身不是解释性的吗?”不。我想理解你的问题,但不。代码有很多错误。代码不是C++。它没有编译。这不是完整的代码,只是一个简单的例子来说明…@Superziyi,这没有帮助。请发布可以编译的代码。原始代码很大…但是要从零开始获得精简版本,我必须创建适合场景的新类。然而,这个例子本身不是不言自明的吗?我不知道发布的每个代码片段都需要能够编译,如果是这样的话,请告诉我。谢谢你!“这个例子本身不是不言自明的吗?”“不,我想理解你的问题,但是不。那段代码有很多错误。谢谢!这意味着,若B并没有拷贝构造函数,那个么我就永远不想在堆栈上使用a和B了?交易是否变得:我要么总是确保两个对象都在堆栈上创建过,并且不需要关心是否得到了析构函数(但这是一个糟糕的设计吗?),要么总是“新建”两个对象(并在以后删除),如果我在堆上新建一个对象?如果一个类没有定义自定义复制或移动构造函数(或赋值),提供了隐式副本构造函数。这个复制构造函数只执行它自己的成员的一个复制。复制构造函数的技巧真是棒极了!这样看来,我可以在堆栈和堆上自由使用A和B了!我想剩下的唯一问题是什么通常是推荐的做法。我想如果我决定只在堆栈上使用对象,我不会声明指针成员,只是一个对象成员…所以如果我希望对象可以以任何一种方式创建,那么你的解决方案可能是最好的选择…实际上还有一个问题…当我以这种方式定义a时,然后初始化a和B,如:“B;a(&B);”有没有在堆上创建过对象B?没有。内存是通过使用“new type[count]”、malloc调用或操作系统API从堆中分配的。谢谢!这意味着,若B并没有拷贝构造函数,那个么我就永远不想在堆栈上使用a和B了?交易是否变得:我要么总是确保两个对象都在堆栈上创建过,并且不需要关心是否得到了析构函数(但这是一个糟糕的设计吗?),要么总是“新建”两个对象(并在以后删除),如果我在堆上新建一个对象?如果一个类没有定义自定义复制或移动构造函数(或赋值),提供了隐式副本构造函数。这个复制构造函数只执行它自己的成员的一个复制。复制构造函数的技巧真是棒极了!这样看来,我可以在堆栈和堆上自由使用A和B了!嗯