C++ 复制构造函数演示(崩溃…)

C++ 复制构造函数演示(崩溃…),c++,copy-constructor,C++,Copy Constructor,这是节目单 class CopyCon { public: char *name; CopyCon() { name = new char; } CopyCon(const CopyCon &objCopyCon) { name = new char; _tcscpy(name,objCopyCon.name); } ~CopyCon() { if( name != NULL ) { delete name;

这是节目单

class CopyCon
{
public:
char *name;

CopyCon()
{ 
    name = new char; 
}

CopyCon(const CopyCon &objCopyCon)
{
    name = new char;
    _tcscpy(name,objCopyCon.name);
}

~CopyCon()
{
    if( name != NULL )
    {
        delete name;
        name = NULL;
    }
}
};

int main()
{
    CopyCon objCopyCon1;
    objCopyCon1.name = "Hai";
    CopyCon objCopyCon2(objCopyCon1);
    objCopyCon1.name = "Hello";
    cout<<objCopyCon2.name<<endl;
    return 0;
}
类CopyCon
{
公众:
字符*名称;
CopyCon()
{ 
名称=新字符;
}
CopyCon(const CopyCon和objCopyCon)
{
名称=新字符;
_tcscpy(名称,objCopyCon.name);
}
~CopyCon()
{
if(name!=NULL)
{
删除姓名;
name=NULL;
}
}
};
int main()
{
CopyCon objCopyCon1;
objCopyCon1.name=“Hai”;
CopyCon objCopyCon2(objCopyCon1);
objCopyCon1.name=“你好”;

cout问题是在复制构造函数中只分配了一个
char

main
中,您分配了一个4字节的字符串(请记住空值),但是当您复制对象时,您只分配了足够的空间容纳1个字节

你可能想做的是改变

name = new char;

在析构函数中:

delete name;

此外:


您正在将
“Hai”
“Hello”
分配给
objCopyCon1.name
,它隐藏在构造函数中分配的内存。此内存永远无法释放!

您写入已分配的变量,这是未定义的行为

当下面的行运行时

 CopyCon objCopyCon1;
 objCopyCon1.name = "Hai";
 CopyCon objCopyCon2(objCopyCon1);
\u tcscpy()
将4个字符(3个字母和空终止符)复制到一个只能合法保存一个字符的缓冲区中。因此,如果写入超过缓冲区结尾,则会导致堆损坏

您需要分配适当大小的缓冲区:

CopyCon(const CopyCon &objCopyCon)
{
    name = new char[_tcslen(objCopyCon.name) +1];
   _tcscpy(name,objCopyCon.name);
}

您还需要将析构函数中的
delete
更改为
delete[]
,并将所有其他
new
调用更改为
new[]
以避免未定义的行为。

复制器的工作应该是创建对象的副本。
name
在两个对象中指向的
char
数组应该具有
相同的大小
相同的内容
,这在您的情况下不会发生。因此更改

name = new char; // allocates only one char


您需要分配足够的内存来保存试图存储的信息。“Hai”是4个字节或字符(包括空终止符),并且您只分配了一个。您也不会使用“=”将字符串从一个内存位置复制到另一个内存位置。您需要跨多个内存位置复制字符串


使用std::string它将使您的生活更加轻松:)

您正在分配一个字符并尝试将多个字符复制到该内存位置。首先找出字符串的长度,然后使用
新字符[length+1]分配
长度+1
字符(额外字符以容纳空字符)
语法。您需要相应地将析构函数更改为
delete[]name

除了大家提到的
new char
问题之外,字符串“Hai”和“Hello”位于只读内存中。这意味着您不能删除它们(但可以在析构函数中删除)-这确实会导致崩溃。您的代码不应直接分配给
名称
,而应使用设置函数,例如:

void set_name(const char *new_name)
{
    delete [] name; // delete is a no-op on a NULL pointer
    name = new char[tcslen(new_name) + 1];
    _tcscpy(name,new_name);
}

老实说,我很惊讶赋值并没有产生编译器警告。您正在将
常量char*
赋值给
char*
,这可能会导致像您看到的那样的各种问题。

这里的代码工作得非常完美

class CopyCon
{
public:
char *name;

CopyCon()
{ 
    name = NULL;        
}

CopyCon(const CopyCon &objCopyCon)
{
    name = new char[_tcslen(objCopyCon.name)+1];
    _tcscpy(name,objCopyCon.name);
}

~CopyCon()
{
    if( name != NULL )
    {
        delete[] name;
        name = NULL;
    }
}

void set_name(const char *new_name) 
{ 
    //delete [] name; // delete is a no-op on a NULL pointer 
    if( NULL != name)
    {
        delete[] name; name = NULL;
    }
    name = new char[_tcslen(new_name) + 1]; 
    _tcscpy(name,new_name); 
} 
};

int main()
{
     CopyCon objCopyCon1;
objCopyCon1.set_name("Hai");
CopyCon objCopyCon2(objCopyCon1);
objCopyCon1.set_name("Hello");
cout<<objCopyCon1.name<<endl;
cout<<objCopyCon2.name<<endl;
return 0;
}
类CopyCon
{
公众:
字符*名称;
CopyCon()
{ 
name=NULL;
}
CopyCon(const CopyCon和objCopyCon)
{
name=newchar[_tcslen(objCopyCon.name)+1];
_tcscpy(名称,objCopyCon.name);
}
~CopyCon()
{
if(name!=NULL)
{
删除[]名称;
name=NULL;
}
}
无效集合名称(常量字符*新名称)
{ 
//delete[]name;//delete是对空指针的不操作
if(NULL!=名称)
{
删除[]名称;名称=空;
}
名称=新字符[\u tcslen(新名称)+1];
_tcscpy(名称、新名称);
} 
};
int main()
{
CopyCon objCopyCon1;
objCopyCon1.集合名称(“Hai”);
CopyCon objCopyCon2(objCopyCon1);
objCopyCon1.set_name(“Hello”);

你在喊什么?神圣的灵魂们,请原谅我,如果它看起来在喊。我只是在寻求帮助……可能有点力不从心。事实上,我已经重新思考了我的问题。@乔治:你说过“这段记忆永远不会被释放!”。那么在哪里分配,在哪里可以释放?您应该有一个成员函数,它设置
name
的值。在该函数中,您可以释放现有值。我认为将“char*”分配给“const char*”应该会引起警告,而不是相反。在构造函数和set\u name中,分配的name=NULL,我正在检查如果(NULL!=name){delete[]name;name=NULL;}否,它总是将常量赋值给生成警告的非常量。这是因为非常量变量的限制比常量变量少。
name = new char[strlen(objCopyCon.name) + 1]; // allocate array of char
void set_name(const char *new_name)
{
    delete [] name; // delete is a no-op on a NULL pointer
    name = new char[tcslen(new_name) + 1];
    _tcscpy(name,new_name);
}
class CopyCon
{
public:
char *name;

CopyCon()
{ 
    name = NULL;        
}

CopyCon(const CopyCon &objCopyCon)
{
    name = new char[_tcslen(objCopyCon.name)+1];
    _tcscpy(name,objCopyCon.name);
}

~CopyCon()
{
    if( name != NULL )
    {
        delete[] name;
        name = NULL;
    }
}

void set_name(const char *new_name) 
{ 
    //delete [] name; // delete is a no-op on a NULL pointer 
    if( NULL != name)
    {
        delete[] name; name = NULL;
    }
    name = new char[_tcslen(new_name) + 1]; 
    _tcscpy(name,new_name); 
} 
};

int main()
{
     CopyCon objCopyCon1;
objCopyCon1.set_name("Hai");
CopyCon objCopyCon2(objCopyCon1);
objCopyCon1.set_name("Hello");
cout<<objCopyCon1.name<<endl;
cout<<objCopyCon2.name<<endl;
return 0;
}