当前位置: 首页 > news >正文

最新新闻热点事件佩洛西百度关键词优化公司哪家好

最新新闻热点事件佩洛西,百度关键词优化公司哪家好,自己建设个小网站要什么手续费,wordpress如何配置伪静态页面目录 1. 为什么学习string类? 1.1 C语言中的字符串 2. 标准库中的string类 2.1 string类 2.2 string类的常用接口说明 1. string类对象的常见构造 2. string类对象的操作 3.vs和g下string结构的说明 3. string类的模拟实现 3.2 浅拷贝 3.3 深拷贝 3.4 写…

目录

1. 为什么学习string类?

1.1 C语言中的字符串

2. 标准库中的string类

2.1 string类

2.2 string类的常用接口说明

1. string类对象的常见构造

2. string类对象的操作

3.vs和g++下string结构的说明

3. string类的模拟实现

 3.2 浅拷贝

3.3 深拷贝

3.4 写时拷贝

3.5 string类的模拟实现


1. 为什么学习string类?

1.1 C语言中的字符串

C 语言中,字符串是以 '\0' 结尾的一些字符的集合,为了操作方便, C 标准库中提供了一些 str 系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP 的思想,而且底层空间需要用户自己管理,稍不留神可 能还会越界访问。

2. 标准库中的string

2.1 string

https://cplusplus.com/reference/string/string/?kw=string

  • 1. 字符串是表示字符序列的类
  • 2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作
  • 单字节字符字符串的设计特性。
  • 3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信
  • 息,请参阅basic_string)
  • 4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits
  • allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)
  • 5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(UTF-8)的序列,这个
  • 类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
总结:
  • 1. string是表示字符串的字符串类
  • 2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  • 3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>
  • string;
  • 4. 不能操作多字节或者变长字符的序列。
使用string类时,必须包含#include头文件以及using namespace std;

2.2 string类的常用接口说明

1. string类对象的常见构造

void Teststring()
{string s1; // 构造空的string类对象s1string s2("hello bit"); // 用C格式字符串构造string类对象s2string s3(s2); // 拷贝构造s3
}

2. string类对象的操作

PS: 

  • 1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()
  • 2. clear()只是将string中有效字符清空,不改变底层空间大小。
  • 3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字 符个数增多时:resize(n)0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变。
  • 4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于
  • string的底层空间总大小时,reserver不会改变容量大小。

3.vsg++string结构的说明

下述结构是在32 位平台下进行验证, 32 位平台下指针占 4个字节。
vs下 string的结构
string总共占 28 个字节 ,内部结构稍微复杂一点,先是 有一个联合体,联合体用来定义 string中字 符串的存储空间:
  1. 当字符串长度小于16时,使用内部固定的字符数组来存放
  2. 当字符串长度大于等于16时,从堆上开辟空间 
union _Bxty
{ // storage for small buffer or pointer to larger onevalue_type _Buf[_BUF_SIZE];pointer _Ptr;char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;
这种设计也是有一定道理的,大多数情况下字符串的长度都小于 16 ,那 string 对象创建好之后,内部已经有了16 个字符数组的固定空间,不需要通过堆创建,效率高。
其次:还有 一个 size_t 字段保存字符串长度,一个 size_t 字段保存从堆上开辟空间总的容量
最后:还 有一个指针 做一些其他事情。
故总共占16+4+4+4=28个字节。
g++ string 的结构
G++ 下, string 是通过写时拷贝实现的, string 对象总共占 4 个字节,内部只包含了一个指针,该指 针将来指向一块堆空间,内部包含了如下字段:
  1. 空间总大小
  2. 字符串有效长度
  3. 引用计数
  4. 指向堆空间的指针,用来存储字符串。
struct _Rep_base
{size_type _M_length;size_type _M_capacity;_Atomic_word _M_refcount;
};

3. string类的模拟实现

PS: string类在自己实现的时候一定要注意浅拷贝问题

上述 String 类没有显式定义其拷贝构造函数与赋值运算符重载,此时编译器会合成默认的,当用 s1 s2 时,编译器会调用默认的拷贝构造。最终导致的问题是, s1 s2 共用同一块内存空间,在释放时同一块 空间被释放多次而引起程序崩溃 ,这种拷贝方式,称为浅拷贝。

 3.2 浅拷贝

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来 。如果 对象中管理资源 ,最后就会 导致多个对象共 享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为 还有效,所以当继续对资源进项操作时,就会发生发生了访问违规

3.3 深拷贝

如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情 况都是按照深拷贝方式提供

3.4 写时拷贝

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。
引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成 1 ,每增加一个对象使用该资源,就给 计数增加1 ,当某个对象被销毁时,先给该计数减 1 ,然后再检查是否需要释放资源,如果计数为 1 ,说明该 对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源。
https://coolshell.cn/articles/12199.html
https://coolshell.cn/articles/1443.html

3.5 string类的模拟实现

//string.h
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace mystr {class string{public://迭代器, 因为字符串底层内存连续, 所以可以简单的定义成指针typedef char* iterator;typedef const char* const_iterator;//配合范围for循环iterator begin() { return _str; }iterator end() { return _str + _size; }//兼容常量字符串const_iterator begin() const { return _str; }const_iterator end() const { return _str + _size; }//string();string(const char* str = "");string(const string& s);string& operator=(string temp) { swap(temp); return *this; }~string() { delete[] _str; _str = nullptr; _size = _capacity = 0; }//返回C语言字符数组const char* c_str() const { return _str; }size_t size() const { return _size; }char& operator[](size_t pos) { assert(pos < _size); return _str[pos]; }const char& operator[](size_t pos) const{ assert(pos < _size); return _str[pos]; }//重置大小void reserve(size_t n);void push_back(char ch) { insert(_size, ch); }void append(const char* str) { insert(_size, str); }string& operator+=(char ch) { insert(_size, ch); return *this; }string& operator+=(const char* str) { insert(_size, str); return *this; };void insert(size_t pos, char ch);void insert(size_t pos, const char* str);void erase(size_t pos = 0, size_t len = npos);size_t find(char ch, size_t pos = 0) {for (size_t i = pos; i < _size; i++) if (_str[i] == ch) return i;return npos;}size_t find(const char* str, size_t pos = 0) { return strstr(_str + pos, str) - _str; }void swap(string& s);string substr(size_t pos = 0, size_t len = npos);bool operator<(const string& s) const { return strcmp(_str, s._str) < 0; }bool operator>(const string& s) const { return !(*this <= s); }bool operator<=(const string& s) const { return !(*this > s); }bool operator>=(const string& s) const { return !(*this < s); }bool operator==(const string& s) const {return strcmp(_str, s._str) == 0; }bool operator!=(const string& s) const { return !(*this == s); }void clear() { _str[0] = '\0'; _size = 0; }private:char* _str;size_t _size;size_t _capacity;//一般static变量的定义要放在类外, 整型是特例const static size_t npos = -1;};void swap(string& s1, string& s2);istream& operator>>(istream& ci, string& s);ostream& operator<<(ostream& co, string& s);
}
//string.cpp
#include "string.h"
namespace mystr {string::string(const char* str):_size(strlen(str)) {_str = new char[_size + 1];_capacity = _size;strcpy(_str, str);}string::string(const string& s) {string temp(s._str);swap(temp);}void string::reserve(size_t n) {if (_capacity < n) {char* temp = new char[n + 1];strcpy(temp, _str);delete[] _str;_str = temp;_capacity = n;}}void string::insert(size_t pos, char ch) {assert(pos <= _size);if (_size == _capacity) {size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;reserve(newcapacity);}size_t end = _size + 1;while (end > pos) _str[end] = _str[end - 1], --end;_str[pos] = ch;_size++;}void string::insert(size_t pos, const char* str) {assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity) reserve(_size + len);size_t end = _size + len;while (end > pos + len - 1) _str[end] = _str[end - len], --end;memcpy(_str + pos, str, len);_size += len;}void string::erase(size_t pos, size_t len) {if (len > _size - pos) _str[pos] = '\0', _size = pos;else strcpy(_str + pos, _str + pos + len), _size -= len;}void string::swap(string& s) {char* temp = _str;_str = s._str;s._str = temp;std::swap(_size, s._size);}string string::substr(size_t pos, size_t len) {if (len > _size - pos) { string sub(_str + pos); return sub; }else {string sub;sub.reserve(len);for (size_t i = pos; i < pos + len; i++) sub += _str[i];return sub;}}void swap(string& s1, string& s2){ s1.swap(s2); }istream& operator>>(istream& ci, string& s) {s.clear();char ch = ci.get();while (ch != ' ' && ch != '\n') s += ch, ch = ci.get();return ci;}ostream& operator<<(ostream& co, string& s) {for (size_t i = 0; i < s.size(); i++) co << s[i];return co;}
}
//test.cpp
#include "string.h"
namespace mystr {void test1() {string s1 = "1111";string s2 = s1;cout << s1.c_str() << endl << s2.c_str() << endl;cout << s1.size() << endl;}void test2() {string s1 = "111";string s2 = "222222";s1 = s2;cout << s1.c_str() << endl;}void test3() {string s1 = "111222333";for (auto& i : s1) i += 3;cout << s1.c_str() << endl;const string s2 = "111222333";for (auto& i : s2) cout << i;cout << endl;for (size_t i = 0; i < s1.size(); i++) cout << (s1[i] += 2);cout << endl;}void test4() {string s1 = "sadfsf";s1.insert(2, '-');cout << s1.c_str() << endl;s1.insert(0, '-');cout << s1.c_str() << endl;s1.insert(2, "11111");cout << s1.c_str() << endl;s1.insert(0, "222222");cout << s1.c_str() << endl;}void test5() {string s1 = "asgfidsgf";s1.push_back('-');cout << s1.c_str() << endl;s1.append("=====");cout << s1.c_str() << endl;s1 += 'w';cout << s1.c_str() << endl;s1 += "0000";cout << s1.c_str() << endl;s1.erase(10);cout << s1.c_str() << endl;s1.erase(7, 100);cout << s1.c_str() << endl;s1.erase(3, 2);cout << s1.c_str() << endl;s1.erase(0);cout << s1.c_str() << endl;}void test6() {string s1 = "ksjfghks";cout << s1.find('h', 2) << endl;cout << s1.find("ghk", 2) << endl;cout << s1.find("ghksgs", 2) << endl;}void test7(){string s1 = "sggsdsdf";string s2 = "sdgfrgdb";cout << s1.c_str() << endl;cout << s2.c_str() << endl;swap(s1, s2);cout << s1.c_str() << endl;cout << s2.c_str() << endl;s1.swap(s2);cout << s1.c_str() << endl;cout << s2.c_str() << endl;string s3 = s1.substr(2, 5);cout << s3.c_str() << endl;}void test8() {string s1, s2;cin >> s1 >> s2;cout << s1 << endl << s2 << endl;}
}
int main() {mystr::test8();return 0;
}

http://www.yayakq.cn/news/34426/

相关文章:

  • 能看网站的浏览器招聘网站开发学徒
  • ftp上传网站 需要什么文件列举网络推广的方式
  • 网站服务器自己搭建兰州网站优化排名
  • 电商pc网站建设方案做网站到底能不能赚钱
  • 怎么申请域名建立网站官网seo是什么意思
  • 怎么做整人的网站网站建设开头
  • 海尔网站建设信息广州工商注册公司注册
  • not found的网站网站推广渠道
  • 自己做服务器的网站网站开发验收确 认书
  • 网站地图 seo潍坊400建网站公司
  • 网站做成app的软件广告推广
  • php网站优化怎么创建个网站
  • Spring做网站和什么华为网络营销案例分析
  • 国外电商网站如何做icp备案wordpress主题重置
  • 淘宝客网站主题下载如何做vip影视网站
  • 企业网站建设是什么实现的物质基础和技术支撑wordpress 首页静态化
  • 做网站怎么找图怎么搜才能搜到网站
  • wordpress两个站点众筹网站开发周期
  • asp.net网站伪静态响应式商品展示的网站
  • 哪能建设网站wordpress excel 检索
  • 建设工程部网站网络营销的途径有哪些
  • 海珠做网站公司关键词搜索推广
  • 苏州建站公司 诚找苏州聚尚网络高端制作网站设计
  • 电子商务网站建设问题广东东莞最新情况
  • 做网站具备的条件wordpress functions.php在哪里
  • ps设计素材网站wordpress 帐号共用
  • 长春网站建设解决方案进入百度app
  • 网站管理助手v3.0九江市建设规划局网站
  • 计算科学与学习网站建设与实施网页制作免费网站
  • 如何做手机网站网站开发 密码