一.标准库中的string 类
1.1 关于string 类的了解
在使用string类的时候,必须包含#include头文件以及using namespace std:
1.2关于auto和范围for
1.auto 现在的用法是suto 不在是一个存储类ing指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期的推到完成。
2.在auto 做声明类型指针时,用auto 和auto* 没有任何区别,但是用auto 声明时必须加上&
3.当在同一行声明多个定义的时候,这些类型必须时相同的类型,否则编译器会报错,因为编译器只会对第一个类型进行推导,然后用推导出来的类型来定义其他的变量。
4.它不能作为函数的参数,可以做返回值,但是建议做返回值时谨慎使用。
5.auto 不能直接用来声明数组
#include<iostream>
using namespace std;
int func1()
{
return 10;
}
//不能做参数
//void func2(auto a)
//{
//
// return 0;
//}
auto func3()
{
return 4;
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = func1();
//auto e;//这里会报无法修改左值的错误
//因为 auto 本身不代表具体类型,它需要根据初始化表达式来确定变量的实际类型。
// 如果没有初始化值(如 auto e;),编译器无法推断 e 应该是什么类型,因此会报错。
cout << typeid(a).name() << endl;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
int x = 10;
auto y = &x;
auto* z = &x;
auto& m = x;
cout << typeid(x).name() << endl;
cout << typeid(y).name() << endl;
cout << typeid(z).name() << endl;
cout << typeid(m).name() << endl;
auto aa = 1, bb = 2;
//auto cc = 3, dd = 5.0;//auto 必须始终推导为同一类型
//数组不能具有其中包含“auto”的元素类型
//auto arry[] = { 1,2,3,4,5 };
return 0;
}
关于auto 的争取用法;
//auto用法
int main()
{
std::map<std::string, std::string> dict = { { "apple", "苹果" },{ "orange",
"橙子" }, {"pear","梨"} };
//在这里auto 可以在std::map<std::string, std::string>::iterator it = dict.begin();
//把std::map<std::string, std::string>::iterator 这个替换成auto
auto it = dict.begin();
while (it != dict.end())
{
cout << it->first << ":" << it->second << endl;
++it;
}
return 0;
}
关于范围for
1. 对于一个有范围的集合而言,C++中引入例如基于范围的for循环,for循环后的括号由冒号" : "分为两个部分:第一部分时范围内用于迭代的变量,第二部分表示被迭代的范围,自动进行迭代,自动取数据,自动判断结束。
2.范围for可以作用到数组和容器对象上进行遍历。
3.范围for的底层很简单,就是迭代器
{
int arry[] = { 1,2,3,4,5 };
//在C++98 的遍历
for (int i = 0; i < sizeof(arry) / sizeof(arry[0]); ++i)
{
arry[i] *= 3;
}
for (int i = 0; i < sizeof(arry) / sizeof(arry[0]); ++i)
{
cout << arry[i] <<endl;
}
//C++11的遍历
for (auto e:arry)
{
e *= 3;
}
for (auto e : arry)
{
cout << e << " " << endl;
}
string str("hello word");
for (auto ch : str)
{
cout << ch << endl;
}
cout<<endl;
return 0;
}
二.string类的模拟实现
2.1经典的string类问题
上面已经对string类进行了简单的介绍,大家只要能够正常使用即可。在面试中,面试官总喜欢让
学生自己来模拟实现string类,最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析
构函数。大家看下以下string类的实现是否有问题?
// 为了和标准库区分,此处使用String
class String
{
public:
/*String()
:_str(new char[1])
{*_str = '\0';}
*/
//String(const char* str = "\0") 错误示范
//String(const char* str = nullptr) 错误示范
String(const char* str = "")
{
// 构造String类对象时,如果传递nullptr指针,可以认为程序非
if (nullptr == str)
{
assert(false);
return;
}
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
~String()
{
if (_str)
{
delete[] _str;
_str = nullptr;
}
}
private:
char* _str;
};
// 测试
void TestString()
{
String s1("hello bit!!!");
String s2(s1);
}

2.2关于浅拷贝
浅拷贝,也被叫做位拷贝,编译器只是将对象中的值拷贝过来,如果对象中管理资源,最后就会呆滞多个对象共享投一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一个对象不知道该资源已经被释放,当对此再进行操作时,就会发生访问违法。
2.3关于深拷贝
2.3.1传统版写法的String类
#include<iostream>
#include<assert.h>
using namespace std;
class String
{
public:
String(const char* str = " ")
{
//构造String类对象,如果传递nullpter指针,可以认为程序非法
if (nullptr == str)
{
assert(false);
return;
}
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
String(const String& s)
:str(new char[strlen(s.str) + 1])
{
strcpy(_str, s.s_tr);
}
String& operator=(const String& s)
{
if (this != &s)
{
char* pStr = new char[strlen(s._str) + 1];
strcpy(pStr, s._str);
delete[]_str;
_str = pStr;
}
return *this;
}
~String()
{
if (_str)
{
delete[]_str;
_str = nullputer;
}
}
private:
char* _str;
}
2.3.2现代版写法的String类
//现代版写法的String类
class String
{
public:
String(const char* str = " ")
{
if (nullptr == str)
{
assert(false);
return;
}
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
String(const String& s)
: _str(nullptr)
{
String strTmp(s._str);
swap(_str, strTmp._str);
}
// 对比下和上面的赋值那个实现比较好?
String& operator=(String s)
{
swap(_str, s._str);
return *this;
}
/*
String& operator=(const String& s)
{
if(this != &s)
{
String strTmp(s);
swap(_str, strTmp._str);
}
return *this;
}
*/
~String()
{
if (_str)
{
delete[] _str;
_str = nullptr;
}
}
private:
char* _str;
};
string类详解与模拟实现

被折叠的 条评论
为什么被折叠?



