在析构函数中将类成员设置为空
Setting class member to null in destructor
本页有一段代码:
class MyString
{
private:
char *m_pchString;
int m_nLength;
public:
MyString(const char *pchString="")
{
// Find the length of the string
// Plus one character for a terminator
m_nLength = strlen(pchString) + 1;
// Allocate a buffer equal to this length
m_pchString = new char[m_nLength];
// Copy the parameter into our internal buffer
strncpy(m_pchString, pchString, m_nLength);
// Make sure the string is terminated
m_pchString[m_nLength-1] = ' ';
}
~MyString() // destructor
{
// We need to deallocate our buffer
delete[] m_pchString;
// Set m_pchString to null just in case
m_pchString = 0;
}
char* GetString() { return m_pchString; }
int GetLength() { return m_nLength; }
};
在析构函数中,编写器将m_pchString设置为null,并说以防万一。如果我们不把它设为空会发生什么?我们已经释放了指定的内存,类成员将在退出时被杀死。这样做的好处是什么?
如果指针设置为NULL
,则使用已删除对象(例如通过指向该对象的悬空指针)的错误实际上可能被隐藏,因为有错误的代码可能会在尝试使用数据之前检查NULL
。在一种思考方式中,这可能被认为是"安全的"行为,但是发生的事情是您实际上隐藏了一个已经发生的缺陷。
请记住,隐藏bug和修复bug是不一样的。在内存被重新分配之后,这个悬浮指针实际上可能会再次被使用,并将一个有效的指针放置在相同的内存位置。此时,有问题的代码将开始使用新的、有效的指针,但原因不正确。
因此,最好将指针设置为如果使用不当会导致崩溃的东西:
m_pchString = (char*) 0xdeaddead;
现在,如果有人试图使用已删除对象的成员指针(这是一个错误),它将很快失败,错误将被捕获而不是隐藏。
在使用MSVC(可能还有其他工具链)的调试构建中,您已经可以通过调试堆获得该行为。MSVC调试堆用值0xdd填充通过free()
或operator delete
释放的内存:https://stackoverflow.com/a/370362/12711
除了Michael Burr提供的答案,在Tietbohl提供的链接的帮助下,这也是一个很好的答案。我引用它:
它可以帮助捕获许多对释放内存的引用(假设您的平台在null指针的转换上出错)。
它不会捕获所有对空闲内存的引用,例如,如果你有一个指针的副本。但有总比没有好。
它将掩盖双重删除,但我发现这些远不如访问已经释放的内存常见。
在很多情况下,编译器会把它优化掉。因此,不必要的论点不能说服我。如果你已经在使用RAII,那么在你的代码中并没有太多的删除,所以额外的赋值导致混乱的论点并不能说服我。
在调试时,看到空值而不是过时的指针通常更方便。
如果这仍然困扰着你,使用智能指针或引用代替。
不设为NULL也无妨。对象删除后,无论如何都不应该访问它的成员数据。
好吧,当你已经删除了内存位置,析构函数只是一个很好的编程实践,它只是帮助在任何隐藏的错误存在
- 嵌套在类中时无法设置成员数据
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- 聚合初始化,将成员指针设置为同一结构成员
- 在类 (C++) 之外设置 const int 成员变量
- 是否可以使用智能指针成员设置具有另一个结构的结构?
- 自定义 QML QQuick彩绘项目成员锚点未在 qml 中设置为父级
- 如何在C++中将 cin 设置为类的成员函数?
- 将 AlphaMode 成员设置为 DXGI_SWAP_CHAIN_DESC1 会使 CreateSwapChainFo
- 在VS2017中,我们如何在项目成员之间共享编译设置
- 如何为类中可能无法计算的成员设置值
- 如何在没有setter的情况下设置类内部类的成员变量?
- 在运行时为随机分布类成员设置最小和最大边界?
- 是否可以在C++中使用初始化列表设置数组的特定成员?
- 设置成员 GlobalCEFApp->OnWebKit使用函数地址初始化 C++生成器
- 一个线程设置成员,而另一个循环上方 - 是此螺纹 - 不安全
- 有没有办法使用显式实例化按类型设置成员变量
- 为什么不能为类实例设置成员值?
- 构造函数不设置成员变量
- 我可以在构造函数调用之前设置成员变量吗?
- 如何仅设置成员(如果存在)