C++基础——类和动态内存分配

new 运算符的作用:为的是在执行程序过程中,动态分配内存,从而减少 不必要的内存分配。

程序中有new,析构函数必不可少,new 对应delete 。

1、默认构造函数

eg:

class test{
public:
    test();//a,第一种表示
    test(int a=0,int b=10);//b,第二种表示
    //所有参数都带默认值亦可以成为默认的构造函数
};

2、复制构造函数

  • 概念:将一个对象复制到 新创建的对象中
  • 作用:只会逐个复制非静态的值(静态成员属于整个类,不是每个对象),这个过程也被称为浅复制
  • 何时调用:当按值传递和返回对象时, 都将调用 复制构造函数
    eg://将对象oldD复制给newD
    test newD(oldD);
    test newD=oldD;
    test newD=test(oldD)
    test *newD=new test(oldD);
    以上均会复制构造函数

默认的复制构造函数逐个复制非静态成员的值(是值,非地址);
故应该按引用 传递对象,节约调用构造函数的时间以及存储新对象的空间。

结合代码

.h申明
class str
{
private:
	char *strr;//字符指针
	int len;//字符长度
	static int num_strings;
public:
	str();
	str(const char*s);
	~str();
	friend std::ostream& operator<<(std::ostream &os, const str &st);
};
.cpp 实现
str::str() //1号构造函数
{
	len = 4;
	strr = new char[len];
	strcpy_s(strr,4,"c++");
	num_strings++;
	std::cout << "default obj created" << "\n";
}
str::str(const char *s)//重载构造函数
{
	len = std::strlen(s);
	strr = new char[len + 1];
	strcpy_s(strr,len+1,s);
	num_strings++;
	std::cout << "obj created" << "\n";
}
str::~str()
{	std::cout << "对象被删除" << "///" << strr<<"\n";
	num_strings--;
	std::cout <<"现存对象" << "///" <<num_strings<<"\n";
	delete[] strr;//使用new [] 创建,必须使用delete[] 来释放;如果为new ,就对应delete即可
	
std::ostream &operator<<(std::ostream &os, const str &st)//重载运算符
{	os << st.strr << "\n";
	return os;}

//str 的调用

//main函数调用
    str a("bobobodadada");
	str b;
	str c = str("asssssssssd");

解释: 这么调用,在释放时不会出现问题,都有对应的构造函数,在释放的时候就能正确的释放。

再添加代码

callme1(a);
callme2(b);
void callme1(str & a)
{
	cout << "引用\n"<<a;
}
void callme2(str a) //== str a=b;
{
	cout << "值\n" << a;
}

解释:
a 引用传递,释放正常,因为不会创建临时变量。
b 按值传递,会报出两个错误如下: num_strings计数错误
报出字符串乱码,以及其他debug中止

b1:会复制构造函数,但是缺少 构造函数 str(const str &s),编译器只会浅复制,并不会执行num_strings++;故创建正常,释放时,数值出错。
b2:因为默认调用的是引用,所以两个变量指向的是同一个地址,由于调用callme2的完成后,将释放a;所以后面在释放callme2(b)的b的时候,就会出现访问地址错误(访问已经被释放的空间)

解决方案如下:
//一些类的成员 是通过动态分配的内存(为指针);这个时候就需要复制它的创建过程;这个过程被称为深复制

str::str(const str &s)
{   len = s.len;
	strr = new char[len + 1];
	strcpy_s(strr, len + 1, s.strr);
	num_strings++; //都会赋给对象的strr指针。所以不存在释放同一个地址的情况
}

继续添加代码

 str dd;
 dd=c;//程序到这都没有错
 cout <<"dd="<<dd <<"\n";
 cout << "c=" << c << "\n";

解释:运行程序报错。
因为调用赋值的时候没得默认的运算构造,系统默认调用 复制运算函数。就会导致两个函数一样,调用引用,和上面一样;对应c++primer plus 436页。

解决方案:对运算符深度复制;添加运算构造函数

str & str::operator=(const str & st)
{	if (this == &st)
		return *this;
	delete[] strr;
	len = st.len;
	strr = new char[len + 1];
	strcpy_s(strr, len + 1, st.strr);
	return *this;
}
//自检查 如果相等 返回this指针的地址;不相等释放空间,重新赋值。

小知识点

深度赋值:类成员如果有指针需要进行深度复制;
浅复制:只是复制变量值,浅复制即可。

c++ 的空指针为 nullptr。不要写成0;

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值