非常幸运的进入了华为公司,开始了我的职业生涯。今天打开CSDN发现以前复习面试笔试的时候有道题还没有搞清楚,现在仔细研究了一下,贴出来我的心得,让大家看看希望对大家有所帮助。
代码如下:
#include
<
string
.h
>
#include < stdio.h >
class Test {
private :
char * name;
public :
Test( char * newName)
{
name = new char [strlen(newName)]; // 1、这里为name分配空间时,只分配了存储newName中字符的空间,但是没有为terminating null character(终止符)分配空间
strcpy(name, newName); // 而在这里调用strcpy时,这个函数会自动会目的字符串加上终止符的,因此这样将会造成错误。
}
Test(Test & t) // 2、这是一个错误的拷贝构造函数,只是浅拷贝,即只把地址拷贝至另外一个对象。当源对象被析构时,所含有的name指针也被销毁。但此时目的对象仍然保留了 name指针,这就是一个dirty pointer,即指向了已被销毁的内存地址,当然要造成错误。
{
name = t.name;
}
~ Test()
{
delete[] name; // 运行到这里的时候就出错了,不知道为什么?
}
void print(Test test) // 3、本程序最大的错误,我也是看了大家的提示才知道的。这里在传入一个Test类型的对象之后,调用完毕时,将会把这个作为参数传入的Test对象的name 指针进行销毁。而在程序结束时,将会调用析构函数运行delete[] name;这条语句销毁name指针,造成重复销毁,造成错误。
{
printf(test.name);
}
};
void main()
{
Test test = Test( " test " );
test.print(test);
}
#include < stdio.h >
class Test {
private :
char * name;
public :
Test( char * newName)
{
name = new char [strlen(newName)]; // 1、这里为name分配空间时,只分配了存储newName中字符的空间,但是没有为terminating null character(终止符)分配空间
strcpy(name, newName); // 而在这里调用strcpy时,这个函数会自动会目的字符串加上终止符的,因此这样将会造成错误。
}
Test(Test & t) // 2、这是一个错误的拷贝构造函数,只是浅拷贝,即只把地址拷贝至另外一个对象。当源对象被析构时,所含有的name指针也被销毁。但此时目的对象仍然保留了 name指针,这就是一个dirty pointer,即指向了已被销毁的内存地址,当然要造成错误。
{
name = t.name;
}
~ Test()
{
delete[] name; // 运行到这里的时候就出错了,不知道为什么?
}
void print(Test test) // 3、本程序最大的错误,我也是看了大家的提示才知道的。这里在传入一个Test类型的对象之后,调用完毕时,将会把这个作为参数传入的Test对象的name 指针进行销毁。而在程序结束时,将会调用析构函数运行delete[] name;这条语句销毁name指针,造成重复销毁,造成错误。
{
printf(test.name);
}
};
void main()
{
Test test = Test( " test " );
test.print(test);
}
上面的三个问题都是经常遇到的。修改正确后的代码如下:
#include
<
string
.h
>
#include < stdio.h >
class Test
{
private :
char * name;
public :
Test() : name(NULL){}
Test( char * newName)
{
name = new char [strlen(newName) + 1 ];
strcpy(name, newName);
}
// 有内存的操作,要自定义拷贝构造函数和赋值构造函数,否则容易产生一些错误
Test( const Test & t)
{
name = new char [strlen(t.name) + 1 ];
strcpy(name, t.name);
}
Test & operator = ( const Test & t)
{
if ( this == & t)
{
return * this ;
}
if (name != NULL)
{
delete []name;
}
name = new char [strlen(t.name) + 1 ];
strcpy(name, t.name);
}
~ Test()
{
delete[] name;
}
void print() // 成员函数,还传递对象做参数?
{
printf(name);
}
};
void main()
{
Test test = Test( " test " );
test.print();
}
#include < stdio.h >
class Test
{
private :
char * name;
public :
Test() : name(NULL){}
Test( char * newName)
{
name = new char [strlen(newName) + 1 ];
strcpy(name, newName);
}
// 有内存的操作,要自定义拷贝构造函数和赋值构造函数,否则容易产生一些错误
Test( const Test & t)
{
name = new char [strlen(t.name) + 1 ];
strcpy(name, t.name);
}
Test & operator = ( const Test & t)
{
if ( this == & t)
{
return * this ;
}
if (name != NULL)
{
delete []name;
}
name = new char [strlen(t.name) + 1 ];
strcpy(name, t.name);
}
~ Test()
{
delete[] name;
}
void print() // 成员函数,还传递对象做参数?
{
printf(name);
}
};
void main()
{
Test test = Test( " test " );
test.print();
}
注意:
1、strlen(char*)函数返回字符串的字符个数,不包括终止符
2、strcpy(char*, char*)函数会自动为目的字符串添加终止符
3、对于第三个问题的描述,感觉不是很清晰,如果有错误的话,希望大家告诉我。