【问题标题】:Shall I build a destructor in this classes?我应该在这个类中构建一个析构函数吗?
【发布时间】:2015-08-07 01:59:39
【问题描述】:

我目前正在使用 C++ 构建 ABM 模型。

我有需要相互交互的类,因为例如B 类需要检查 A 类中的值并对其返回一些评估,然后 C 类可能想要读取这些值。类不需要更改其他类的值,只需从中读取。

我当前的实现中的 B 类有一个 po inter 指向包含类 A 的所有成员的向量。指针存在有两个原因:它使初始化向量更容易,并且向量留在 main 的范围内,以便我可以访问和循环它,调用每个代理的 A 类成员。

我的 MCVE:

#include <iostream> 
#include <vector>

using namespace std;

class A;    // Forward declaration

class B{

    int id,
    some_value;

    vector<A> * A_vec;

public:

// Overloaded constructor
    B(int ID, vector<A> & PTR)
    {   
    A_vec = & PTR;
    id = ID;
    some_value = 0;
    };

// Copy Constructor
    B( const B& that ):
    id(that.id),
    some_value(that.some_value)
    {
    // Pointer ??
    };

// Non-default destructor -> uncomment leads to seg_fault
    /*
    ~B(){   delete [] A_vec;};
    */
// Assignment operator

    B& operator=(const B& that)
    {
        id = that.id;
        some_value = that.some_value;
    // Pointer ??
        return *this;
    };

//Methods to update different variables go here ..
    void do_stuff();

};

class A{

    B & class2_ref;
    vector<double> o;


public:

    int stuff;

// Overloaded constructor

    A(int STUFF, B & REF, vector<double> O):

    class2_ref(REF),
    o(O)

    {
        stuff = STUFF;  
    };

// Methods to update different variables go here ..
};  

void B::do_stuff()
{
    int L = A_vec->size();  
    for(int l = 0; l<L; l++)  some_value += (*A_vec)[l].stuff; // Perform some operation

};


int main(){

    int I = 5;          // Number of objects of A

    vector<double> O(12,2); // Some numbers in here

    B b(0,A_vec);

    for(int i = 0; i< I; i++)
    {
        A a(i,b,O);
        A_vec.push_back(a);
    }

    b.do_stuff();

    cout<< "Debugging MCVE" << endl;

    return 0;
}

那么我的问题是:

我应该在 B 类中实现析构函数/复制构造函数/赋值运算符吗? A类呢?如果是这样,请您指出正确的语法(对于析构函数,上面的 cmets 会导致段错误)。

我的理解是,这可能是我对指针的“浅”破坏感到满意的情况之一,因为class Bvector&lt;A&gt; 都将超出返回语句的范围。 class B 拥有指针,该指针在到期时被破坏,向量也是如此。

那么,三人法则中的另一个成员呢?

只计划了一个 B 类对象,但我可能(很小的机会)以后想概括一下。

【问题讨论】:

  • 请先格式化您的代码。
  • 另外,没有必要 delete 一个你从来没有 new 的指针,这可以解释段错误
  • @SoheilHassasYeganeh 我格式化了,希望现在更好。
  • @Alejandro 我认为这是段错误的原因。不过我想知道,因为我一直在阅读原始指针数据成员需要在析构函数中加以注意。那么,考虑到在构造函数中初始化它的方式,它是安全的吗?复制呢?
  • 你必须释放你分配的东西。最好是首先分配的人将是解除分配的人。这是RAII的(其中一个)含义(资源获取是初始化)

标签: class c++11 vector


【解决方案1】:

如果一个类有一个指针类型,你应该实现一个析构函数,我建议也实现一个复制和一个赋值运算符,否则你会从两个不同的地方处理同一个对象,这可能会导致你错误,例如 -

void someFunction(B &b)
{
  B a = b;
}

B b(0,A_vec);
someFunction(b); //After finishing someFunction, it will try to delete the vector from a , but it is the same vector you used in b.
b.do_stuff(); // Would cause a seg error

而对于析构函数的语法,只是删除向量,而不是它的内容,它会在内容上使用向量默认的析构函数:

delete A_vec

如果它没有初始化,请确保你不使用它,我建议只在类的每个 ctor 上构建一个空向量,这样你就不会遇到段错误,你可以使用 delete。

【讨论】:

  • 在 dtor 中使用 delete A_vec 和它所在的类会导致双重释放错误。另外,我希望将指针保留在类内以指向它之外的向量。我不想在里面有另一个向量和外面的副本,我也不希望只有一个向量但在类内。
  • 我假设你想概括,如你所说,因此有超过 1 B,请记住 delete[] 和 delete 之间的区别,使用 delete A_vec 将擦除矢量内容,使用 delete [] A_vec 将尝试在 A_vec 的每个成员上使用 A dtor,而不使用任何东西只会简单地擦除指针,将向量留在堆中。
  • 我明白了,但我仍然希望在类之外有多个向量。
  • 作为一般规则,如果你在类中有 * 类型,你将需要一个 dtor,否则你将有内存泄漏(如果你在其他地方不处理它),我也是建议没有作为成员的参考,还编辑了上一条评论,该死的输入导致它被提前发送:)
  • 一般来说,是的。这里怎么样?我目前的理解是,我上面的内容是安全的。我主要有一个向量。我在课堂上有一个指针。指针只是一个保存内存地址的变量。在 return 语句中,类被销毁,默认 dtor 处理指针,但不接触向量。然后vector被销毁,再次调用它的默认析构函数。
猜你喜欢
  • 2010-09-26
  • 2011-03-17
  • 2020-04-06
  • 1970-01-01
  • 2012-07-30
  • 2020-12-15
  • 1970-01-01
  • 2021-02-03
相关资源
最近更新 更多