前言
上篇博客学习了一些string类的模拟实现erase、find、substr、比较大小、流输入、流输出,这篇博客将介绍剩下的一些string的知识以及vector的一些使用方式。
string
传统深拷贝的写法
//拷贝构造
string(const string& s)
{
_str = new char[s._capacity + 1];
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
}
//拷贝赋值
string& operator=(const string& s)
{
if (this != &s)
{
delete[] _str;
_str = new char[s._capacity + 1];
strcpy(_str,s._str);
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
手动将字符串的空间进行调整
现代深拷贝的写法
void swap(string& s)
{
std::swap(_str,s._str);
std::swap(_size,s._size);
std::swap(_capacity, s._capacity);
}
//拷贝构造
string(const string& s)
{
string tmp(s._str);
swap(tmp);
}
//拷贝赋值
string& operator=(const string& s)
{
if (this != &s)
{
string tmp(s);
swap(tmp);
}
return *this;
}
string& operator=(string s)
{
swap(s);
return *this;
}
利用swap将数据进行深拷贝
从中我们可以知道,string中的swap底层也是靠std中的swap实现的。
写时拷贝与引用计数
写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。
引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给计数增加1,当某个对象被销毁时,先给该计数减1,然后再检查是否需要释放资源,如果计数为1,说明该对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源。
我们知道深拷贝存在的问题:
- 需要析构两次
- 一个数据修改了会影响另一个数据
而写时拷贝可以让一个数据被删除时,另一个数据不会被影响
oj题
反转字符串中的单词 III
反转字符串中的单词 III-力扣
思路:
- 利用find找空格的位置
- 利用reverse将每个词进行反转
- 最后利用rfind找到最后一个空格的位置,将最后一个词进行反转
class Solution {
public:
string reverseWords(string s) {
int end=s.find(" ");
int begin=0;
while(end != -1)
{
reverse(s.begin()+begin,s.begin()+end);
begin=end+1;
end=s.find(" ",begin);
}
end=s.rfind(" ");
reverse(s.begin()+end+1,s.end());
return s;
}
};
字符串相乘
字符串相乘-力扣
思路:
- 将两个字符串进行反转
- 创建数组,遍历将乘积存入数组
- 接着进行进位
- 最后将数组中的数字倒着进行输出即可
class Solution {
public:
string multiply(string num1, string num2) {
if(num1 == "0" || num2 == "0")
return "0";
reverse(num1.begin(),num1.end());
reverse(num2.begin(),num2.end());
int s1=num1.size(),s2=num2.size();
int* ans=new int[s1+s2]{0};
for(int i=0;i<s1;i++)
{
for(int j=0;j<s2;j++)
{
ans[i+j] +=(num1[i]-'0')*(num2[j]-'0');
}
}
for(int i=0;i<s1+s2;i++)
{
if(ans[i]>9)
{
int t=ans[i];
ans[i]=t%10;
ans[i+1]+=(t/10);
}
}
int pos=(ans[s1+s2-1] == 0 ? s1+s2-2:s1+s2-1);
string s;
for(;pos>=0;--pos)
{
s+=(ans[pos]+'0');
}
return s;
}
};
vector
vector接口介绍
- vector的构造函数
⁂ 代表重点
vector的构造函数 | 说明 |
---|---|
vector()⁂ | 无参构造 |
vector(size_type n, const value_type& val = value_type()) | 构造并初始化n个val |
vector((const vector& x)⁂ | 拷贝构造 |
vector (InputIterator first, InputIterator last) | 使用迭代器进行构造 |
- vector的输出方式
⁂ 代表重点
vector的输出方式 | 说明 |
---|---|
范围for | 从头到尾遍历 |
operator[] ⁂ | 返回vector中n处的元素的引用 |
begin()+end() ⁂ | 获取第一个数据位置的iterator 获取最后一个数据的下一个位置的iterator |
rbegin()+rend() | 获取第一个数据位置的reverse_iterator, 获取最后一个数据的reverse_iterator |
cbegin()+cend() | 获取第一个数据位置的const_iterator, 获取最后一个数据的下一个位置的const_iterator |
crbegin()+crend() | 获取第一个数据位置的const_reverse_iterator, 获取最后一个数据的const_reverse_iterator |
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v;
vector<int> v2(10, 2);
for (auto i : v2)
{
cout << i << " ";
}
cout << endl;
vector<int> v4(v2);
for (int i = 0; i < v4.size(); i++)
{
cout << v4[i] << " ";
}
cout << endl;
vector<int> v3(++v2.begin(), --v2.end());
vector<int>::iterator it = v3.begin();
while (it != v3.end())
{
cout << *it << " ";
it++;
}
cout << endl;
vector<int> v5(20, 3);
vector<int>::reverse_iterator rit = v5.rbegin();
while (rit != v5.rend())
{
cout << *rit << " ";
rit++;
}
cout << endl;
return 0;
}
- vector的析构函数
- operator= ⁂
将新内容分配给容器,替换其当前内容,并相应地修改其大小。
#include<iostream>
#include<vector>
using namespace std;
void vector_test2()
{
vector<int> v1(10, 1);
vector<int> v2(20, 2);
for (auto i : v2)
{
cout << i << " ";
}
cout << endl;
v2 = v1;
for (auto i : v2)
{
cout << i << " ";
}
cout << endl;
}
int main()
{
vector_test2();
return 0;
}
- vector 空间增长问题
⁂ 代表重点
容量空间 | 接口说明 |
---|---|
size ⁂ | 获取数据个数 |
max_size | 获取数据最大个数 |
resize ⁂ | 改变vector的size |
capacity ⁂ | 获取数据容量大小 |
empty | 判断是否为空 |
reserve ⁂ | 改变vector的capacity |
shrink_to_fit | 减小容量大小使其适应数据 |
#include<iostream>
#include<vector>
using namespace std;
void vector_test3()
{
vector<int> v(15, 2);
cout << v.size() << endl;
cout << v.capacity() << endl;
v.resize(5);
cout << v.size() << endl;
cout << v.capacity() << endl;
v.resize(20);
cout << v.size() << endl;
cout << v.capacity() << endl;
v.reserve(5);
cout << v.size() << endl;
cout << v.capacity() << endl;
v.reserve(50);
cout << v.size() << endl;
cout << v.capacity() << endl;
cout << v.empty() << endl;
v.shrink_to_fit();
cout << v.size() << endl;
cout << v.capacity() << endl;
}
int main()
{
vector_test3();
return 0;
}
注意:
- reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
- resize在开空间的同时还会进行初始化,影响size。
#include<iostream>
#include<vector>
using namespace std;
void TestVectorExpand()
{
size_t sz;
vector<int> v;
sz = v.capacity();
cout << "making v grow:\n";
for (int i = 0; i < 100; ++i)
{
v.push_back(i);
if (sz != v.capacity())
{
sz = v.capacity();
cout << "capacity changed: " << sz << '\n';
}
}
}
int main()
{
TestVectorExpand();
return 0;
}
由此可知在vs2020的环境下,扩容的速度是1.5倍速
#include<iostream>
#include<vector>
using namespace std;
void TestVectorExpand()
{
size_t sz;
vector<int> v;
sz = v.capacity();
v.reserve(100);
cout << "making v grow:\n";
for (int i = 0; i < 100; ++i)
{
v.push_back(i);
if (sz != v.capacity())
{
sz = v.capacity();
cout << "capacity changed: " << sz << '\n';
}
}
}
int main()
{
TestVectorExpand();
return 0;
}
- vector的调整
⁂ 代表重点
vector的调整 | 接口说明 |
---|---|
assign | 分配vector内容 |
push_back ⁂ | 尾插 |
pop_back ⁂ | 尾删 |
insert | 在position之前插入val |
erase | 删除position位置的val |
swap | 交换两个vector的数据空间 |
clear | 清除vector的数据 |
#include<iostream>
#include<vector>
using namespace std;
void vecotr_test4()
{
vector<int> v(10,5);
v.assign(5, 4);
for (auto i : v)
{
cout << i << " ";
}
cout << endl;
vector<int> v2(10, 2);
v2.push_back(6);
for (auto i : v2)
{
cout << i << " ";
}
cout << endl;
v2.pop_back();
for (auto i : v2)
{
cout << i << " ";
}
cout << endl;
vector<int> v3(10,3);
vector<int>::iterator it = v3.begin();
v3.insert(it,2, 1);
for (auto i : v3)
{
cout << i << " ";
}
cout << endl;
vector<int>::iterator it2 = v3.begin();
v3.erase(it2,it2+2);
for (auto i : v3)
{
cout << i << " ";
}
cout << endl;
vector<int> v4(10, 1);
vector<int> v5(5, 2);
for (auto i : v4)
{
cout << i << " ";
}
cout << endl;
for (auto i : v5)
{
cout << i << " ";
}
cout << endl;
swap(v4, v5);
for (auto i : v4)
{
cout << i << " ";
}
cout << endl;
for (auto i : v5)
{
cout << i << " ";
}
cout << endl;
v5.clear();
for (auto i : v5)
{
cout << i << " ";
}
cout << endl;
}
int main()
{
vecotr_test4();
return 0;
}
标签:begin,capacity,cout,vector,oj,string,size
From: https://blog.csdn.net/2302_79180171/article/details/142456667