在析构函数C ++中删除指针

时间:2018-05-17 08:56:26

标签: c++ oop pointers

我正在使用图书馆的课程。让它成为A,它有一个字符指针" token"

我的代码:

void someFunction()
{
    A a;
    cout<<a.token;
    anotherFunction(a);
    cout<<a.token;  //  line 4: now token became invalid [1]
}

void anotherFunction(A copyOfA);
{
   //  doing something
}  //  on exit destructor of copyofA will be called

[1]为什么它变得无效:A类如下:

class A
{
    char *token;
    public:
    A()
    {
        token = GetRandomToken();   // GetRandomToken will return a 'new Char' array
    }
    ~A()
    {
        if(token != NULL)
        {
            delete[] token;    // it is A's responsibility to delete the memory it created
            token = NULL;
        }
    }
};
调用copyOfA的析构函数anotherFunctiontoken中的

被删除。因此在第4行,令牌无效,因为a.token和copyOfA.token都指向到同一地址。

在下列情况下,解决方案是什么:

案例1:class A位于给定的库中:因此我无法对其进行修改。

案例2:如果我可以修改class A:处理此问题的好方法是什么?

我知道,如果通过传递引用调用anotherFunction,我就不会遇到这个问题。但是,如果我必须在某个时刻保留对象的副本呢?

在此处查看示例代码:https://ideone.com/yZa4k4

2 个答案:

答案 0 :(得分:3)

如果您无法修改class A,则应避免复制它。我认为最安全的方法是动态分配class A对象:

void anotherFunction(std::shared_ptr<A> aPtr)
{
    // please also note that in your case token is PRIVATE
    std::cout << aPtr->token << std::endl;
}

std::shared_ptr<A> aPtr(new A);
std::cout << aPtr->token << std::endl;
anotherFunction(aPtr);

或者,如果您坚持使用堆栈分配,则应将anotherFunction签名更改为:

void anotherFunction(const A& a)
{
    std::cout << a.token << std::endl;
}

通过const引用传递你的参数(避免复制构造函数)。

现在,如果您可以修改class A,则应该应用the rule of three/five/zero,因为您有非平凡的析构函数。执行此操作的懒惰方法是将其他构造函数声明为已删除(然后,就像在您的示例中,您无法复制A对象,但您也可以保证没有人会尝试这样做):

class A
{
    public:
    // for this example purpose I made token PUBLIC, but it is a bad idea in general
    char *token;
    A()
    {
        token = GetRandomToken();   // GetRandomToken will return a 'new Char' array
    }
    ~A()
    {
        if(token != NULL)
        {
            delete[] token;    // it is A's responsibility to delete the memory it created
            token = NULL;
        }
    }
    A(const A& other) = delete;
    A(A&& other) = delete;
};

或者,如果你不懒,你实际上可以考虑如何将内存从一个对象中的token指针复制到另一个对象 - 这取决于你如何实现它。这取决于GetRandomToken的要求和实施。

答案 1 :(得分:-1)

如果您的示例准确,则class A没有正确的复制构造函数,因此会删除两个实例的令牌。 这导致双重删除,因为第一个实例中的指针没有改变。