[c++学习]剑指offer1题的学习笔记

这篇博客记录了学习第一题时遇到的困惑和解决方法:

1. 为什么返回对象的引用?

参考 http://www.cnblogs.com/codingmengmeng/p/5871254.html

重载运算符返回void、返回对象本身、返回对象引用。返回对象引用基于下面两个原因:

a.允许进行连续赋值

b. 虽然返回对象也可以连续赋值,但是返回对象时要调用拷贝函数和析构函数导致不必要的开销,降低赋值运算符等的效率。

赋值运算符的本意为“返回左值的引用”。

举例解释返回对象和返回:

#include <iostream>
using namespace std;
class String
{
private:
	char *str;
	int len;
public:
	String(const char* s);//构造函数声明
	String operator=(const String& another);//运算符重载,此时返回的是对象
	void show()
	{
		cout << "value = " << str << endl;
	}

	/*copy construct*/
	String(const String& other)
	{
		len = other.len;
		str = new char[len + 1];
		strcpy(str, other.str);
		cout << "copy construct" << endl;
	}

	~String()
	{
		delete[] str;
		cout << "deconstruct" << endl;
	}
};

String::String(const char* s)//构造函数定义
{
	len = strlen(s);
	str = new char[len + 1];
	strcpy(str, s);
}

String String::operator=(const String &other)//运算符重载
{
	if (this == &other)
		return *this;
	//        return;
	delete[] str;
	len = other.len;
	str = new char[len + 1];
	strcpy(str, other.str);
	return *this;
	//    return;
}

int main()
{
	String str1("abc");
	String str2("123");
	String str3("456");
	str1.show();
	str2.show();
	str3.show();
	str3 = str1 = str2;//str3.operator=(str1.operator=str2)    
	str3.show();
	str1.show();
	getchar();
	return 0;
}
赋值运算符返回的是类型本身, 输出结果如下:

value = abc

value = 123

value = 456

copy construct

copy construct

deconstruct

deconstruct

value = 123

value = 123

若改为: String&operator+(const String& str)

结果为:

value = abc

value = 123

value = 456

value = 123

value = 123

 

举例说明返回对象引用符合原始语义清晰:

    (str3= str1) = str2;

一般来说,我们认为上式是将str1赋值给str3,然后str2的值再赋值给str3;

当返回的是对象的引用时:

#include <iostream>
using namespace std;
class String
{
private:
	char *str;
	int len;
public:
	String(const char* s);//构造函数声明
	String& operator=(const String& another);//运算符重载,此时返回为空
	void show()
	{
		cout << "value = " << str << endl;
	}

	/*copy construct*/
	String(const String& other)
	{
		len = other.len;
		str = new char[len + 1];
		strcpy(str, other.str);
		cout << "copy construct" << endl;
	}

	~String()
	{
		delete[] str;
		cout << "deconstruct" << endl;
	}
};

String::String(const char* s)
{
	len = strlen(s);
	str = new char[len + 1];
	strcpy(str, s);
}

String& String::operator=(const String &other)
{
	if (this == &other)
		return *this;
	//        return;
	delete[] str;
	len = other.len;
	str = new char[len + 1];
	strcpy(str, other.str);
	return *this;
	//    return;
}

int main()
{
	String str1("abc");
	String str2("123");
	String str3("456");
	str1.show();
	str2.show();
	str3.show();
	(str3 = str1) = str2;
	cout << "str3的内容为:" << endl;
	str3.show();
	getchar();
	return 0;
}

输出结果为:

value = abc

value = 123

value = 456

str3的内容为:

value = 123

当返回的是对象时:(改为String operator=(constString& another);)

输出结果为:

value = abc

value = 123

value = 456

copy construct

copy construct

deconstruct

deconstruct

str3的内容为:

value = abc

原因:在执行(str3=str1)后,因为返回的是对象(一个临时对象,str3的一个拷贝),不是引用,str2是对一个临时对象赋值,使用str3的内容保持不变。


2. 构造函数和析构函数的形式(C++primer笔记)(我认为多看几遍程序的效果会更好)

构造函数:

构造函数的名字与类名相同,但构造函数没有返回类型。

Sales_data()=default;//默认构造函数

Sales_data (const std::string &s) : bookNo(s){}//冒号以及冒号和花括号之间的代码,这部分称为构造函数初始值列表,它负责为新创建的对象的一个或几个数据成员赋初值


3.delete a 与delete [] a的区别:

a.针对简单类型 使用new分配后不管是数组还是非数组形式内存空间用这两种形式均可,例如:

int *a=new int[10];

delete a;

delete [] a;

原因是:分配简单类型内存时,内存大小已经确定,系统可以记忆并管理,在析构时,系统不会调用析构函数,它直接通过指针可以获取实际分配的内存空间

b.针对class,两种表达体现出具体差异

class A

{

private:

  char* m_cBuffer;

  int m_nlen;

public:

  A(){m_cBuffer=newchar [m_nLen];}

  ~A(){delete []m_cBuffer;}

};

A * a=new A[10];

delete a;//仅释放了a指针指向的全部内存空间,也就是只调用了a[0]对象的析构函数,剩下的a[1]到a[9]自行分配到m_cBuffer对应内存空间将不能释放,从而造成内存泄漏

delete [] a;//调用使用类对象的析构函数释放用户自己分配内存空间并且释放了a指针指向的全部内存空间。

 

所以总结下就是,如果ptr代表一个用new申请的内存返回的内存空间地址,即所谓的指针,那么: 

delete   ptr   代表用来释放内存,且只用来释放ptr指向的内存。  

delete[]   rg   用来释放rg指向的内存,!!还逐一调用数组中每个对象的destructor!! 

   对于像int/char/long/int*/struct等等简单数据类型,由于对象没有destructor,所以用delete 和delete [] 是一样的!但是如果是C++对象数组就不同了。

  举例学习:

#include<iostream>
using namespace std;
class Babe {
public:
	Babe() {
		cout << "Creatr a Babe to talk with me"<<endl;
	}
	~Babe() {
		cout << "Babe do not go away,listen to me" << endl;
	}
};
int main() {
	Babe* pbabe = new Babe[3];
	//delete pbabe;//会引发中断
	//pbabe = new Babe[3];
	delete [] pbabe;
	getchar();
	return 0;
}


输出

Creatr a Babe to talk with me

Creatr a Babe to talk with me

Creatr a Babe to talk with me

Babe do not go away,listen to me

 

Creatr a Babe to talk with me

Creatr a Babe to talk with me

Creatr a Babe to talk with me

Babe do not go away,listen to me

Babe do not go away,listen to me

Babe do not go away,listen to me

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值