在C 中调用破坏者

Invoking of destructors in C++

本文关键字:破坏者 调用      更新时间:2023-10-16

以下代码具有一个用户定义的数据类型,称为String。此类的Objects存储char指针str(for String的短手)和length

#include<iostream>
#include<cstring>
using namespace std;
class String
{
    char* str;
    int length;
public:
    String(){}                     //default constructor 
    String(const char* s)
    {
        length=strlen(s);
        str=new char[length+1];   
        strcpy(str,s);
    }
    void add(String a,String b)   //function to concatenate strings
    {
        length=a.length+b.length;
        str=new char[length+1];
        strcpy(str,a.str);
        strcat(str,b.str);
    }
    void display()
    {
        cout<<str<<endl;
    }
    ~String()                                //destructor 
    {
        delete str;
        cout<<"Destructor invoked!";
    }
};
int main()
{
    String s1;
    String s2("Well done!");
    String s3("Boy");
    s1.add(s2,s3);
    s1.display();
    s2.display();
    s3.display();
}

输出:

Destructor invoked!Destructor invoked!Well done!boy
X!!;
<!!;
Destructor invoked!Destructor invoked!Destructor invoked!
  • 似乎甚至在 display功能被调用。这是什么?

如果未定义删除函数函数,我将获得以下输出(如预期):

Well done!boy
Well done!
boy 
  • 为什么在定义破坏者时会出乎意料的输出?

此默认构造函数

String(){} 

没有初始化任何内容,因为两个数据成员是基本类型,而基本类型没有提供自动初始化。

因此,对结果实例的任何使用都将使用不确定的值(数据成员的),因此将具有未定义的行为。

修复:初始化数据成员。


您还需要负责复制和移动,例如避免双delete s&ndash;这也是未定义的行为。

示例代码复制了呼叫中的 String实例

s1.add(s2,s3);

&hellip;因为add按值进行参数。

修复:定义至少一个复制构造函数。


在破坏者中deadlocation

delete str;

&hellip;不匹配使用new[]str的分配。

它可以在实践中起作用,但这是不确定的行为,因此可能引起各种问题。

修复:使用delete[]用于使用new[]创建的东西。


修复上述代码后仍将泄漏内存。一个简单的修复程序可能是定义串联构造函数,让add使用它来创建新的String实例,然后使用swap该实例和当前实例的状态。这种方法具有自动(几乎是自动)为异常安全的优点。


一般建议:

  • 而不是<cstring>,只需使用<string.h>即可。一个优点是,就像同名的C标头一样,它可以保证将名称放在全球名称空间中。因此,如果您使用诸如strcpy之类的不合格的名称,它将不仅可以使用,而不仅仅是通过手头编译器的碰巧。

  • void add(String a,String b)中的值一样,而不是通过value 传递潜在的大对象,通过将它们传递给const ,如void add(String const& a,String const& b)所示,以避免不必要的复制。<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

  • 在与I/O无关的类中,优先不做I/O,例如void display()成员函数。例如,display()功能在图形用户界面中无法使用。

您需要复制构造函数: void add(String a,String b);最好通过引用通过字符串:

void add(const String &a, const String &b);

也需要在Destructor中使用删除[]。

释放内存
delete[] str;

现在它将起作用。