1.析构函数的注意点
在构造函数中,分配了堆空间,但是没有释放,现在是在main函数中实例化对象,程序退出是会释放,但是如果是在某个子函数里面实例化对象
把main函数里面的测试代码都放到一个字函数里面
析构函数
persion4.cpp
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <unistd.h>
using namespace std;
class Persion {
private:
char* name;
int age;
char* work;
public:
Persion()
{
//cout<<"Persion()"<<endl;
this->name = NULL;//注意这里,如果构造函数没有初始化,就需要初始化为NULL,不然在析构函数中会奔溃,也就是说有一个异常地址被释放,程序会奔溃
this->work = NULL;//
}
Persion(char* name)
{
//cout<<"Persion(char* name)"<<endl;
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->work = NULL;
}
Persion(char* name, int age, char* work)
{
//cout<<"Persion(char* name, int age, char* work)"<<endl;
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->age = age;
this->work = new char[strlen(work) + 1];
strcpy(this->work, work);
}
~Persion()
{
cout<<"~Persion()"<<endl;
if(this->name)
delete this->name;
if(this->work)
delete this->work;
}
void setName(char* n)
{
name = n;
}
int setAge(int a)
{
if(a < 0 || a > 150)
{
age = 0;
return -1;
}
age = a;
return 0;
}
void printInfo(void)
{
cout<<"name = "<<name<< "age = "<<age<<endl;
}
};
void test_func()
{
Persion per1;
Persion per2("zhangsan");
Persion per4("zhangsan", 16, "teacter");
Persion *per5 = new Persion;
Persion *per6 = new Persion();
Persion *per7 = new Persion[2];
Persion *per8 = new Persion("lisi", 18, "student");
per8->printInfo();
per4.printInfo();
delete per5;
delete per6;
delete []per7;
delete per8;
}
int main(int argc, char** argv)
{
for(int i = 0;i < 10000; i++)
test_func();
cout<<"test_func end..."<<endl;
sleep(60);
return 0;
}
2.堆释放,程序崩溃——拷贝函数
进行两次堆释放,程序崩溃,因为他们指向的是同一块内存,所以这时不能用默认的拷贝构造函数,我们要自己来定义
示例
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <unistd.h>
using namespace std;
class Persion {
private:
char* name;
int age;
char* work;
public:
Persion()
{
//cout<<"Persion()"<<endl;
this->name = NULL;
this->work = NULL;
}
Persion(char* name)
{
//cout<<"Persion(char* name)"<<endl;
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->work = NULL;
}
Persion(char* name, int age, char* work ="none")
{
//cout<<"Persion(char* name, int age, char* work)"<<endl;
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->age = age;
this->work = new char[strlen(work) + 1];
strcpy(this->work, work);
}
/*这里进行两次堆释放,程序崩溃,因为他们指向的是同一块内存,所以这时不能用默认的拷贝构造函数,我们要自己来定义*/
/*
Persion(Persion &per)
{
//cout<<"Persion(char* name, int age, char* work)"<<endl;
this->name = new char[strlen(per.name) + 1];
strcpy(this->name, per.name);
this->age = per.age;
this->work = new char[strlen(per.work) + 1];
strcpy(this->work, per.work);
}
*/
~Persion()
{
cout<<"~Persion()"<<endl;
if(this->name){
cout<<"name = "<<this->name<<endl;
delete this->name;
}
if(this->work){
cout<<"work = "<<this->work<<endl;
delete this->work;
}
}
void setName(char* n)
{
name = n;
}
int setAge(int a)
{
if(a < 0 || a > 150)
{
age = 0;
return -1;
}
age = a;
return 0;
}
void printInfo(void)
{
cout<<"name = "<<name<< "age = "<<age<<endl;
}
};
int main(int argc, char** argv)
{
/*如果定义了这个构造参数,编译正常,运行会提示重载error: call of overloaded 'Persion(const char [9], int)' is ambiguous*/
Persion per("zhangsan", 18);
Persion per2(per);
per2.printInfo();
return 0;
}
运行错误如下
root@b84a7489540f:/home/CPP/02# ./persion
name:dog
Dog v1 by colin
Persion(char* name, int age)
name=colin, age=34,work=(null)
~Persion()
name=colin
~Persion()
name=
*** Error in `./persion': double free or corruption (fasttop): 0x00000000018ed010 ***
Aborted (core dumped)
也发现一个奇怪的现象,按理main函数中Persion per("zhangsan", 18);应该是对应Persion(char* name, int age);但实际它能匹配到Persion(char* name, int age, char* work ="none")
当我分工合作的方式的时候是不行的,如下:
main.cpp
#include <stdio.h>
#include "persion.h"
#include "dog.h"
#include <iostream>
#include <unistd.h>
using namespace std;
using namespace A;
int main(int argc, char** argv)
{
//Persion per2("colin", 34);//匹配的是Persion::Persion(char* name, int age),如果不定义编译都会报错,但是拷贝函数直接段错误
/*Persion(char* name, int age)
Persion(Persion &per)
Segmentation fault (core dumped)*/
Persion per2("colin", 34, "doctor");//匹配的是Persion::Persion(char* name, int age, char* work = "none")
Persion per3(per2);
per3.printinfo();
return 0;
}
Persion.cpp
#include <stdio.h>
#include <string.h>
#include "persion.h"
#include <iostream>
using namespace std;
namespace A{
Persion::Persion()
{
cout<<"Persion()"<<endl;
//this->name = NULL;
//this->work = NULL;
name = NULL;
work = NULL;
}
Persion::Persion(char* name)
{
cout<<"Persion(char* name)"<<endl;
this->name = new char[strlen(name)+1];
strcpy(this->name, name);
this->work = NULL;
}
/*
Persion::Persion(char* name, int age)
{
cout<<"Persion(char* name, int age)"<<endl;
this->name = new char[strlen(name)+1];
strcpy(this->name, name);
if(age < 0 || age > 150)
{
this->age = 0;
}
this->age = age;
this->work = NULL;
}*/
Persion::Persion(char* name, int age, char* work = "none")
{
cout<<"Persion(char* name, int age, char* work)"<<endl;
this->name = new char[strlen(name)+1];
strcpy(this->name, name);
if(age < 0 || age > 150)
{
this->age = 0;
}
this->age = age;
this->work = new char[strlen(work)+1];
strcpy(this->work, work);
}
Persion::Persion(Persion &per)
{
cout<<"Persion(Persion &per)"<<endl;
this->name = new char[strlen(per.name) + 1];
strcpy(this->name, per.name);
this->age = per.age;
this->work = new char[strlen(per.work) + 1];
strcpy(this->work, per.work);
}
Persion::~Persion()
{
cout<<"~Persion()"<<endl;
if(this->name)
{
cout<<"name="<<name<<endl;
delete this->name;
}
}
void Persion::setName(char* name)
{
this->name = name;
}
int Persion::setAge(int age)
{
if(age < 0 || age > 150)
{
this->age = 0;
return -1;
}
this->age = age;
return 0;
}
void Persion::setWork(char* work)
{
this->work = work;
}
{
printf("name=%s, age=%d,work=%s\n", name, age, work);
}
void printVersion(void)
{
cout<<"persion v1 by colin"<<endl;
}
};
根据这个例子,我理解,构造函数是拷贝所有的成员函数,所以,初始化时必须给每个成员赋值
如果没有赋值,我们自定义的拷贝函数里面会立马判定有非法地址(这就不清楚为啥它会这样了),导致直接段错误,程序无法运行