我实现了一个构造函数,它接受一个字符串作为参数,这会导致析构函数被调用两次然后程序崩溃(程序包含一个原始指针)。我知道它与复制构造函数有关,当使用这种类型的构造函数时,它会以某种方式被调用。下面是一个简单的代码,说明了这个问题。
我很感激您对如何修复程序以避免崩溃的评论。我需要使用这种构造函数。 我想了解为什么复制构造函数被调用。我没有做任何明确的任务。
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class DebugClass
{
public:
DebugClass(void) {
data = NULL;
}
DebugClass(std::string str) {
data = new double[2];
data[0] = 1.0;
data[1] = 2.0;
}
DebugClass(DebugClass const& other) {
cout << "copy construction\n";
}
~DebugClass(void) {
if (data)
{
delete [] data;
data = NULL;
}
}
double* data;
};
int main()
{
DebugClass obj = DebugClass("Folder");
return 0;
}
答案 0 :(得分:6)
您的副本构造函数离开data
未初始化:
DebugClass::DebugClass(DebugClass const& other)
{
cout << "copy construction\n";
}
因此,从该点开始使用任何数据都会产生不确定的行为。
如果您只是将data
设置为nullptr
,那么您就不应该进行双重删除。虽然您可能真的想从other
进行某种形式的复制。
这一行:
DebugClass obj = DebugClass("Folder");
导致复制构造函数被构造为构造obj
。
如果您改为:
DebugClass obj("Folder");
然后obj
将使用普通构造函数构建。
答案 1 :(得分:1)
DebugClass obj = DebugClass("Folder");
rhs创建一个无名对象并分配给obj,这是另一个新对象创建,因此调用了复制构造函数。
您的陈述相当于
DebugClass obj1;
DebugClass obj2 = obj1; // here copy-ctor gets invoked
对于第二部分......虽然你已经定义了一个复制程序,但它对你的程序几乎没有好处,因为你没有对指针数据成员做任何事情,而这个成员是未初始化的。这导致了不确定的行为。
虽然我不知道你对类DebugClass的意图,但是以更简单的方式可以使用另一个数据成员array_size
定义它,你可以如下所示。
DebugClass(void):array_size(0) {
data = NULL;
}
DebugClass(std::string str, size_t aSize):array_size(aSize)
{
if(array_size)
{
data = new double[array_size];
data[0] = 1.0;
data[1] = 2.0;
}
}
DebugClass(DebugClass const& other):array_size(other.array_size)
{
cout << "copy construction\n";
if(array_size)
{
data = new double[array_size];
for(int i=0; i<array_size; i++)
data[i] = other.data[i];
}
}
希望这澄清。