剑指Offer学习笔记(一)

下半年要找工作了,作为一个技术不牛、代码能力弱的小硕,表示很揪心,也为自己的编码能力深深的汗颜,也许自己并不太适合程序猿这个工作吧!

Anyway, 还是要好好复习和学习的,尤其是要锻炼自己的编码能力,希望可以找到理想的工作。希望可以通过记录博客来鞭策自己好好复习。

不管未来工作如何,掌握基础的专业知识,也是对一年后要结束的学生生涯的一个交代吧!fighting~~~

看书提供的代码,发现自己有这几个问题还没有搞明白。

1. _tmain和main的区别

_tmain()是windows提供的对unicode字符集和ANSI字符集进行自动转换用的程序入口点函数。是main的一个别名,在<stdafx.h>中有宏定义,即

#include <stdio.h> #include <tchar.h>,其中头文件<tchar.h>中有它的宏定义:

#define _tmain  main

预编译后,_tmain变成了main.

main()是标准C++函数入口,默认字符编码格式ANSI。

2.P24. 面试题1. 赋值运算符函数

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

class CMyString
{
public:
	CMyString(char* pData=NULL);
	CMyString(const CMyString& str);
	~CMyString(void);

	//声明返回值的类型为引用,才能允许连续赋值
	CMyString& operator = (const CMyString& str);
	void Print();

private:
	char* m_pData;
};

CMyString::CMyString(char *pData)
{
	if (pData == NULL)
	{
		m_pData = new char[1];
		m_pData[0] = '\0';
	}
	else
	{
		int length = strlen(pData);
		m_pData = new char[length + 1];
		strcpy(m_pData, pData);
	}
}

CMyString::~CMyString()
{
	delete[]m_pData;
}

CMyString::CMyString(const CMyString& str)
{
	int length = strlen(str.m_pData);
	m_pData = new char[length + 1];
	strcmp(m_pData, str.m_pData);
}
CMyString& CMyString::operator=(const CMyString& str)
{
	/*
	* 1.普通写法
	if (this == &str)
		return *this;
	delete[]m_pData;
	m_pData = NULL;//释放内存
	m_pData = new char[strlen(str.m_pData) + 1];//若内存不足则会导致new char抛出异常,m_pData会是空指针
	strcpy(m_pData, str.m_pData);
	return *this;*/
	
	/*
	* 2.考虑异常安全性写法,先创建临时实例,在交换临时实例和原来的实例
	* 然而运行结果并不太对。。输出的有问题。。????感觉这个有点问题。
	
	if (this != &str) 
	{
		CMyString strTemp(str);
		// 需要交换,因为对象的两个实例空间上不能有交集
		char * pTemp = strTemp.m_pData;
		strTemp.m_pData = m_pData;
		m_pData = pTemp;
	}
	return *this;*/

	/*
	* 3. 考虑异常安全性,先用new分配新内容,再用delete释放已有内容
	*/
	if (this == &str)
	{
		return *this;
	}
	char *pTemp = new char[strlen(str.m_pData) + 1];
	delete[]m_pData;
	m_pData = NULL;
	m_pData = pTemp;
	strcpy(m_pData, str.m_pData);
	return *this;
}
void CMyString::Print()
{
	cout << m_pData << endl;
}

void Test1()
{
	cout<<"测试1(把实例赋值给另一个实例)"<<endl;
	char* text = "hello test1";
	CMyString str1(text);
	CMyString str2;
	str2 = str1;
	cout << "预期结果:" << text << endl;
	cout << "实际结果:";
	str2.Print();
	cout << endl;
}
void Test2()
{
	cout << "测试2(把实例赋值给自己)" << endl;
	char* text = "hello test2";
	CMyString str1(text);
	str1 = str1;
	cout << "预期结果:" << text << endl;
	cout << "实际结果:";
	str1.Print();
	cout << endl;
}
void Test3()
{
	cout << "测试3(连续赋值)" << endl;
	char* text = "hello test3";
	CMyString str1(text);
	CMyString str2, str3;
	str3 = str2 = str1;
	cout << "str2预期结果:" << text << endl;
	cout << "str2实际结果:";
	str2.Print();
	cout << endl;

	cout << "str3预期结果:" << text << endl;
	cout << "str3实际结果:";
	str3.Print();
	cout << endl;
	system("pause");
}
int main(int argc, char* argv[])
{
	Test1();
	Test2();
	Test3();
	return 0;
}

其实关于内存不足的异常,感觉第二种方法是有问题的,我跑出来结果是不对的。还没有探索到原因。

3. 关于C++中的内存泄露

一般是指堆中的内存泄露。堆内存是手动malloc/realloc/new申请的,程序不会自动回收,需调用free或delete手动释放,否则会引起内存泄露【即要成对出现】。此外,还包括系统资料泄露,如socket连接使用完要释放。
申请和释放必须成对出现malloc/realloc对应free,new对应delete。前者不会运行构造/析构函数,后者会。
看被人总结了内存泄露的原因:
1. 编码错误:即堆内存malloc/realloc/new申请后,未手动释放。
2. 无主内存:申请后,指针指向内存起始地址,若丢失或修改该指针,申请的内存将丢失,且未释放。
3. 异常分支导致资源未释放
4. 隐式内存泄露:程序运行中不断申请内存,直到程序结束才释放。但因为很多程序运行时间长,来不及释放导致内存耗尽。
5. 类的析构函数为非虚函数:析构函数为虚函数,利用多态性调用指针指向对象的析构函数,而不是基类的析构函数。
详细内容在下面博客中有详细介绍:http://blog.csdn.net/kangroger/article/details/39317503


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值