在C 中调用破坏者
Invoking of destructors in C++
以下代码具有一个用户定义的数据类型,称为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;
现在它将起作用。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- 在销毁派生成员之前,在破坏者中调用共同功能
- 为什么我的破坏者只称呼一次,而不是在删除(a)调用上
- 即使在明确调用破坏者后,对象自动破坏也是如此
- 在C 中调用delete []内部破坏者
- 编译器如何处理基类破坏者在派生的破坏者中调用
- 不调用C 破坏者
- 第二个dll中的静态实例的破坏者未被调用
- 在C 中调用破坏者
- 琐碎的破坏性和调用破坏者的必要性