c++ 类的复制构造及赋值运算-练习题

本文探讨了C++中类的复制构造函数和赋值运算符的浅复制概念,并强调了当类包含指针成员时深复制的必要性。同时讲解了静态成员的外部定义方式以及友元函数的声明。通过实例,区分了复制构造函数与赋值运算符的调用场景,建议在需要深复制的情况下同时重写两者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <iostream>
#include <cstring>
using namespace std;

class Str
{
private:
	static int num; // 实例计数器
	char *str;
public:
	Str(){str=0;} // 指向0,防止delete时程序崩溃!
	Str(char *s) // 普通构造函数
	{
		num ++;
		str = new char[strlen(s)+1];
		strcpy(str, s);
	}
	// 深复制 复制构造函数
	Str(Str &s) 
	{
		num ++;
		str = new char[strlen(s.str)+1];
		strcpy(str, s.str);
	}
	// 深复制 赋值运算符
	Str& operator=(Str &s) 
	{
		if (&s==this) // 判断是不是赋值给自己(很重要!)
			return *this;
		num ++;
		delete[] str; // 释放之前str指向的内存(很重要!因此在构造函数中要将str指向某个确定的内存,如果没有,会造成崩溃)
		str = new char[strlen(s.str)+1];
		strcpy(str, s.str);
		return *this;
	}
	// 返回引用使得可以通过a[1]='a'修改某个字符的值
	char& operator[](int i) 
	{
		return str[i];
	}
	// 只返回值,不允许修改数据
	char operator[](int i) const 
	{
		return str[i];
	}

	void show()
	{
		cout<<num<<" string: "<<str<<" 地址:"<<(int*)str<<endl;
	}
	~Str()
	{
		cout<<endl;
		cout<<num<<" 析构: "<<str<<" 地址:"<<(int*)str<<endl;
		num--;
		delete[] str;
	}
};

int Str::num=0;

int main()
{
	if (1)
	{
		char* ss = "some string";
		Str q(ss);
		q.show();
		// 复制构造函数
		Str w = q; // Str w(q);  Str w = Str(q); Str *w = new Str(q);
		w.show();
		// 赋值运算符
		Str e;
		e = q;
		e.show();
		// 赋值给自己则直接返回自己
		e = e;
		e.show();
		// 重载[] 实现修改字符
		e[0] = 'e';
		e.show();

		// 对于const对象,必须定义[] const方法,否则无法使用[]
		const Str r("duck");
		// 如果没有 char operator[](int i) const, 则无法使用[],因为编译器不知道[]会不会修改r
		cout<<"r[0] = "<<r[0]<<endl;
	}
	
	cin.get();
}


运行结果如下:




几点说明如下:

  1. 类的默认 复制构造函数 和 赋值运算符 都是浅复制,即直接复制成员中的值(包括普通值与地址(指针))
  2. 在类的成员中,如果没有使用指针,则浅复制完全可行!
  3. 类的成员中一旦含有指针,则必须自行定义复制构造函数,以实现深复制
  4. 类的静态成员只能在类外定义,以 int A::a=1; 的形式,注意前面不能加 static;只有类内申明时才需要加 static,相同原理的还有友元函数的 friend 标识。
  5. 注意 A a=b; 和 A a; a= b; 的区别:前者调用 复制构造函数 ,后者调用 赋值运算符,因此如需深复制,最好将2个都重写!!!
  6. 其他语言细节详见代码中的注释
下图说明了深复制和浅复制的区别:(图片来自c++ primer plus)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值