剑指offer(一)

本文深入探讨C++编程语言的关键概念,包括sizeof()函数的行为、复制构造函数的正确使用、赋值运算符重载的实现及其陷阱。通过具体示例,讲解如何避免内存泄漏和栈溢出等问题,同时对比nullptr和NULL、delete与delete[]的区别。

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

对编程语言的考核:

  1. 针对C++概念,如各种关键字,

sizeof()空类型大小为1,即使类内有构造析构函数也一样,但是为虚函数时,会在实例中加入一个指向虚函数表的指针,sizeof为4/8

  1. 给出已有的程序,分析运行结果

class 复制构造函数A(A other)传入的参数是A的一个实例,形参复制到实参会调用复制构造函数,如果允许复制构造函数传值,会在复制构造函数内调用复制构造函数,永无休止的递归调用导致栈溢出,修改成A& other即可,为避免变动,加入const

  1. 要求应聘者定义一个类或实现类内成员函数

01赋值运算符函数

考察运算符函数、常量引用、内存泄漏

函数功能

赋值运算符=,对类创建的实例,将a赋给b
要学会想测试案例,可能出现的情况是
1.CMyString a= CMyStrin b一个实例赋给另一个
2.CMyString a=a将实例赋给自己
3.CMyString a=b=c连续赋值

流程

先写类,包括构造函数,析构函数,成员函数先命名
在test中调用

先写类
class CMyString {
public:
	CMyString(char* pData = nullptr);		//初始化,将字符串赋给该类实例,默认空
	CMyString(const CMyString & str);	//初始化,将实例A赋给B
	~CMyString(void);		//析构
	CMyString& operator = (const CMyString &str);		//赋值运算符重载
	void Print();		//打印值
private:
	char *m_pData;
};
test测试用例
void test01() {

	char* text = "hello world";
	CMyString str1(text);	//将字符串“”传给CMyString型对象
	CMyString str2;
	str2 = str1;

}

void test02() {

	char* text = "hello world";
	CMyString str1(text);
	str1 = str1;
	str1.Print();
	
}

void test03() {

	char* text = "hello world";
	CMyString str1(text);
	CMyString str2,str3;
	str3 = str2 = str1;

}
对类内构造函数、析构函数定义
//传入pdata字符串,赋给类内变量
CMyString::CMyString(char* pData) {
	if (pData == nullptr) {
		m_pData = new char[1];
		m_pData = '\0';
	}
	else {
		int length = strlen(pData);
		m_pData = new char[length + 1];
		strcpy(m_pData, pData);
	}
}

CMyString::CMyString(const CMyString &str) {
	int length = strlen(str.m_pData);
	m_pData = new char[length + 1];
	strcpy(m_pData, str.m_pData);
}
CMyString::~CMyString() {
	delete[] m_pData;
}

nullptr和NULL区别

在C语言中,我们使用NULL表示空指针,NULL实际上是一个void *的指针,C++中不能将void *类型的指针隐式转换成其他指针类型,而又为了解决空指针的问题,所以C++中引入0来表示空指针,0比NULL可以让我们更加警觉,但是我们并没有避免这个问题。这个时候C++ 11的nullptr就很好的解决了这个问题我们在C++ 11中使用nullptr来表示空指针

delete和delete[]区别

delete 释放new分配的单个对象指针指向的内存 delete[] 释放new分配的对象数组指针指向的内存

赋值运算符重载
CMyString& CMyString::operator=(const CMyString & str) {
	//如果赋值相同,返回
	if (this == &str)
		return *this;
	//删除原有的
	delete[] m_pData;
	m_pData = nullptr;

	int length = strlen(str.m_pData);
	m_pData = new char[length + 1];
	strcpy(m_pData, str.m_pData);

	return *this;
}

赋值运算符重载的坑

返回值的类型为该类型的引用,如果为void,就不能连续赋值,因为返回自身,类型为该类,且为引用
在函数结束前返回实例自身的引用(*this),只有返回自身的引用,才能连续赋值
传入参数的类型申明为常量引用,如不为常量引用,从形参到实参会调用一次复制构造函数,引用可以避免这种消耗,const不会改变传入的状态。
释放实例自身的内存,如果在分配新内存之前忘了释放,会出现内存泄露
判断传入的参数和当前的实例是否是同一个实例。如果是,则不进行赋值操作。否则在释放时把自身也释放了,就找不到赋值的内容了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值