C++常见错误1

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;
}
};




根据这个例子,我理解,构造函数是拷贝所有的成员函数,所以,初始化时必须给每个成员赋值

如果没有赋值,我们自定义的拷贝函数里面会立马判定有非法地址(这就不清楚为啥它会这样了),导致直接段错误,程序无法运行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值