4

可能的重复:
什么是三法则?

我在以下程序中遇到了双重释放内存的问题。

调试器显示问题出在push_back()函数中。

A类:

class A {
    public:
        A(int x);
        int x;
};

A::A(int x) {
    this->x = x;
}

B类:

class B {
    public:
        B(int x);
        ~B();
        A* a;
};

B::B(int x) {
    this->a = new A(x);
}

B::~B() {
    delete a;
}

主功能:

int main() {
    vector<B> vec;

    for(int i = 0; i < 10; i++) {
        vec.push_back(B(i)); <------------ Issue is here
    }

    cout << "adding complete" << endl;

    for(int i = 0; i < 10; i++) {
        cout << "x = " << (vec[i].a)->x << endl;
    }

    return 0;
}

这段代码有什么问题?

编辑:错误double free or memory corruption

4

3 回答 3

6

您忘记定义一个复制构造函数和复制赋值运算符,因此您的包装对象正在delete被一些B.... 然后当一些副本B超出范围时再次。

在这种情况下,它是B(i)您确定的行上的临时文件,以及向量中实现定义的副本数。

遵守三法则

于 2012-11-12T16:12:45.217 回答
4

您的代码中的问题是由于“普通” C/C++ 指针没有所有权概念。当指针被复制时,两个副本* “认为”他们拥有数据,导致双重删除。

认识到这一事实,C++ 标准库的设计者引入了一个unique_ptr<T>类来帮助您解决此类问题。


*指针的一份副本在B传递给的实例中push_back;指针的另一个副本是在实例中输入的vector

于 2012-11-12T16:12:54.200 回答
2

注意三法则

其他人都已经对此进行了反复强调,所以我不会进一步深入。

要解决您显然试图完成的用法(并在消除过程中遵守三规则),请尝试以下操作。虽然每个人都对正确管理动态成员的所有权是绝对正确的,但您可以轻松地制作您的特定样本以完全避免使用它们。

A级

class A {
    public:
        A(int x);
        int x;
};

A::A(int x) 
   : x(x)
{
}

B类

class B {
    public:
        B(int x);
        A a;
};

B::B(int x) 
    : a(x) 
{
}

主程序

int main() {
    vector<B> vec;

    for(int i = 0; i < 10; i++) {
        vec.push_back(B(i));
    }

    cout << "adding complete" << endl;

    for(int i = 0; i < 10; i++) {
        cout << "x = " << vec[i].a.x << endl;
    }

    return 0;
}

底线 不要使用动态分配,除非您有充分的理由,并且它由包含变量(如智能指针或大力实践三规则的类)终身保护。

于 2012-11-12T19:30:54.577 回答