1.今日复习
104.二叉树最大深度,100.相同的树(判断条件有误),226.翻转二叉树,101.对称二叉树(满足的四个条件1.左右不为空且值不相等2.左右为空3.左不为空,右为空4.左为空。右不为空)
2.简单实现string类的一部分功能
string的构造函数实现了用于初始化string的对象,并且重载了<<操作符,目的是为了让它能够直接打印string类型的字符串,这里要注意,在os输出流当中,我的string类型对象是无法直接访问到string类中的私有成员的,需要将这个重载函数置为string类的友元类,才可以访问到string类的私有成员。
class String {
private:
char* m_buffer;
unsigned int m_size;//无符号整形代表大于零的整数
public:
String(const char* string) {// 实现字符串拷贝
m_buffer = new char[m_size + 1];
m_size = strlen(string);
memcpy(m_buffer,string,m_size+1);
}
friend std::ostream& operator<<(std::ostream& os, const String string);
};
std::ostream& operator<<(std::ostream& os,const String string) {
os << string.m_buffer;
return os;
}
int main() {
String string = "Cherno";
String second = string;
//string[2] = 'a';
std::cout << string << std::endl;
std::cout << second << std::endl;
//std::cin.get();
}
此时的代码是有潜在问题的,如果说我设置了析构函数,在执行析构函数的时候会造成二次析构(报错如上所示),(浅拷贝),所以我们应该调整一下,因为默认的拷贝构造函数是浅拷贝,所以我们应该显示的定义一下拷贝构造函数,
String(const String& other) :m_size(other.m_size) {//实现深拷贝的代码
m_buffer = new char[m_size + 1];
memcpy(m_buffer,other.m_buffer,m_size+1);
}
在运行的过程中,我一直崩溃,最后发现原来是因为构造函数中我是这么写的
String(const char* string) {// 实现字符串拷贝
m_buffer = new char[m_size + 1];
m_size = strlen(string);
memcpy(m_buffer,string,m_size+1);
m_buffer[m_size] = 0;
}
而实际上在m_buffer执行时,m_size还没有被初始化,所以要注意执行的顺序,当我调换完位置之后就可以正常运行了。
最后整体代码如下:
class String {
private:
char* m_buffer;
unsigned int m_size;//无符号整形代表大于零的整数
public:
String(const char* string) {// 实现字符串拷贝
m_size = strlen(string);
m_buffer = new char[m_size + 1];
memcpy(m_buffer,string,m_size+1);
m_buffer[m_size] = 0;
}
//String(const String& other) :m_buffer(other.m_buffer), m_size(other.m_size) {//默认拷贝构造
//}
char& operator[](unsigned int index) {
return m_buffer[index];
}
~String() {
delete[] m_buffer;
}
String(const String& other) :m_size(other.m_size) {//实现深拷贝的代码
m_buffer = new char[m_size + 1];
memcpy(m_buffer,other.m_buffer,m_size+1);
}
friend std::ostream& operator<<(std::ostream& os, const String& string);
};
std::ostream& operator<<(std::ostream& os,const String& string) {
os << string.m_buffer;
return os;
}
int main() {
String string = "Cherno";
String second = string;
string[2] = 'a';
std::cout << string << std::endl;
std::cout << second << std::endl;
std::cin.get();
}
简单介绍一下易错点:
String string=“cherno”
这里的=并不是赋值运算符,是初始化,表明String类对象string隐式调用以“cherno”为唯一参数的构造函数,这种隐式调用特性可通过explicit(在对应构造函数前)关键字关闭
String string;string=“cherno”
这里的=才是赋值运算符,一是重载赋值运算符,接受字符串类型赋值给类。二是如果存在以“cherno”为唯一参数的构造函数,并且没有explicit(即允许隐式调用),编译器将隐式调用该构造函数生成一个临时String类对象,并用这个临时对象给string赋值,此时调用的是以String类为参数重载,可以自定义,如果没有自定义,编译器会自动生成,不过是浅拷贝
3.explicit关键字的作用
1.在修饰构造函数时,可以防止隐式转换和复制初始化
2.在修饰转换函数时,可以防止隐式转换。