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

Deleting a pointer in destructor C++

本文关键字:指针 C++ 析构函数 删除      更新时间:2023-10-16

我正在使用库中的类。让它成为 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;
}
}
};

anotherFunction调用 copyOfA 的析构函数时token被删除。因此,在第 4 行,token 无效,因为 a.token 和 copyOfA.token 都指向相同的地址。

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

情况 1:class A在给定的库中:所以我无法修改它。

案例2:如果我能修改class A:处理这个问题的好方法是什么?

我知道,如果通过传递引用调用另一个函数,我就不会遇到这个问题。但是,如果我必须在某个时候保留对象的副本怎么办?

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

如果您不能修改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;
}

通过常量引用传递参数(避免复制构造函数(。

现在,如果你可以修改你的class A,你应该应用三/五/零的规则,因为你有非平凡的析构函数。执行此操作的懒惰方法是将其他构造函数声明为已删除(然后,就像在您的示例中一样,您无法复制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的要求和实施。

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