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

Cpp::STL—string类的模拟实现(12)

文章目录

  • 前言
  • 一、string类各函数接口总览
  • 二、默认构造函数
    • string(const char* str = "");
    • string(const string& str);
      • 传统拷贝写法
      • 现代拷贝写法
    • string& operator=(const string& str);
      • 传统赋值构造
      • 现代赋值构造
    • ~string();
  • 三、迭代器相关函数
    • begin & end
  • 四、容量和大小相关函数
    • size & capacity
    • reserve
    • resize
    • empty
  • 五、修改字符串相关函数
    • c_str
    • push_back
    • append
    • operator+=
    • insert
    • erase
    • clear
    • swap
    • substr
  • 六、访问字符串相关函数
    • operator[ ]
    • find
  • 七、关系运算符重载函数
  • 八、 流插入与流提取
    • 流插入
    • 流提取
    • getline
  • 总结


前言

  string类的模拟实现源代码
  我好像把string类的模拟实现给遗漏了
  没关系,我们现在来补!


一、string类各函数接口总览

  同样我们先来简单看下我们要实现的接口,另外为了避免跟库里面的string发生冲突,我们要用自己的命名空间包起来:

namespace HQ
{class string{public:typedef char* iterator;typedef const char* const_iterator;iterator begin();iterator end();const_iterator begin() const;const_iterator end() const;// string(); // 无参和带参往往可以合成同一个string(const char* str = "");string(const string& str);string& operator=(const string& str);~string();const char* c_str() const;size_t size() const;char& operator[](size_t pos);const char& operator[](size_t pos) const;void reserve(size_t n = 0);void push_back(char ch);void append(const char* str);string& operator+=(char ch);string& operator+=(const char* str);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);size_t find(const char* str, size_t pos = 0);void swap(string& str); // string自己实现一个,std里的代价极大string substr(size_t pos = 0, size_t len = npos);bool operator<(const string& s) const;bool operator>(const string& s) const;bool operator<=(const string& s) const;bool operator>=(const string& s) const;bool operator==(const string& s) const;bool operator!=(const string& s) const;void clear();private:// char _buff[16];char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;const static size_t npos;};istream& operator>> (istream& is, string& str);ostream& operator<< (ostream& os, const string& str);
}

不要害怕,跟着我一步一步来看!

二、默认构造函数

string(const char* str = “”);

我们设置缺省函数,可是我们试想一下,缺省值给nullptr合理吗?

显然不合理,因为成员变量应该无论如何要先赋值个\0,即默认构造为空字符串,而""(没有空格)就自带一个\0

string::string(const char* str) // 缺省值声明和定义分离:_size(strlen(str)) // 不算\0,且字符串大小才用初始化列表来初始化,这是顺序的原因
{// 三个strlen效率低,用_size来初始化_str = new char[_size + 1]; // 为存储字符串开辟空间(多开一个用于存放'\0')_capacity = _size; // 不算\0strcpy(_str, str); // 将C字符串拷贝到已开好的空间
}

string(const string& str);

拷贝构造,在实现之前我们再来回顾一下深拷贝和浅拷贝的定义:

浅拷贝:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间。其中一个对象的改动会对另一个对象造成影响。
深拷贝:深拷贝是指源对象与拷贝对象互相独立。其中任何一个对象的改动不会对另外一个对象造成影响

很明显,我们并不希望拷贝出来的两个对象之间存在相互影响,因此,我们这里需要用到深拷贝。下面提供深拷贝的两种写法

传统拷贝写法

在这里插入图片描述
先开辟一块足以容纳源对象字符串的空间,然后将源对象的字符串拷贝过去,接着把源对象的其他成员变量也赋值过去即可。因为拷贝对象的_str与源对象的_str指向的并不是同一块空间,所以拷贝出来的对象与源对象是互相独立的

string::string(const string& str):_str(new char[str._capacity + 1]),_size(str._size),_capacity(str._capacity)
{strcpy(_str, str._str);
}

现代拷贝写法

在这里插入图片描述
现代写法与传统写法的思想不同,先根据源字符串的C字符串调用构造函数构造一个tmp对象,然后再将tmp对象与拷贝对象的数据交换即可。拷贝对象的_str与源对象的_str指向的也不是同一块空间,是互相独立的

string::string(const string& s)
{string tmp(s._str);swap(tmp);
}

string& operator=(const string& str);

赋值运算符重载,与拷贝构造函数类似,赋值运算符重载函数的模拟实现也涉及深浅拷贝问题,我们同样需要采用深拷贝

传统赋值构造

传统写法与拷贝构造函数的传统写法几乎相同,只是左值的_str在开辟新空间之前需要先将原来的空间释放掉,并且在进行操作之前还需判断是否是自己给自己赋值,若是自己给自己赋值,则无需进行任何操作

string& string::operator=(const string& str)
{// 考虑到两个字符串的长度可能不太一样// 干脆直接销毁旧的,新开一个拷贝过去if (this != &str) {char* tmp = new char[str._capacity + 1];strcpy(tmp, str._str);delete[] _str;_str = tmp;_size = str._size;_capacity = str._capacity;}return *this;
}

现代赋值构造

通过采用“值传递”接收右值的方法,让编译器自动调用拷贝构造函数,然后我们再将拷贝出来的对象与左值进行交换即可,但是这里为了避免自己给自己赋值,我们还是选择引用传值,在内部在拷贝构造一个临时字符串用来交换

string& string::operator=(const string& str)
{if (this != &str) // 防止自己给自己赋值{string tmp(str); // 用s拷贝构造出对象tmpswap(tmp); // 交换这两个对象}return *this; // 返回左值(支持连续赋值)
}

~string();

string类的析构函数需要我们进行编写,因为每个string对象中的成员_str都指向堆区的一块空间,当对象销毁时堆区对应的空间并不会自动销毁,为了避免内存泄漏,我们需要使用delete手动释放堆区的空间

string::~string()
{delete[] _str; // 不会产生矛盾,就算只有一个底层也是调用delete _str;_str = nullptr;_size = _capacity = 0;
}

三、迭代器相关函数

  string类中的迭代器实际上就是字符指针,只是给字符指针起了一个别名叫iterator而已

注:不是所有的迭代器都是指针
typedef char* iterator;
typedef const char* const_iterator;

begin & end

begin函数的作用就是返回字符串中第一个字符的地址
end函数的作用就是返回字符串中最后一个字符的后一个字符的地址(即’\0’的地址)

string::iterator string::begin()
{return _str;
} string::iterator string::end()
{return _str + _size;
}string::const_iterator string::begin() const
{return _str;
}string::const_iterator string::end() const
{return _str + _size;
}

四、容量和大小相关函数

size & capacity

因为string类的成员变量是私有的,我们并不能直接对其进行访问,所以string类设置了size和capacity这两个成员函数,用于获取string对象的大小和容量

size函数用于获取字符串当前的有效长度(不包括’\0’)
capacity函数用于获取字符串当前的容量(不包括’\0’)

size_t string::size() const
{return _size;
}size_t string::capacity() const
{return _capacity;
}

reserve

其规则:

  1. 当n大于对象当前的capacity时,将capacity扩大到n或大于n
  2. 当n小于对象当前的capacity时,什么也不做

代码中使用strncpy进行拷贝对象C字符串而不是strcpy,是为了防止对象的C字符串中含有有效字符’\0’而无法拷贝(strcpy拷贝到第一个’\0’就结束拷贝了)

void string::reserve(size_t n)
{if (n > _capacity){char* tmp = new char[n + 1];strncpy(tmp, _str, _size + 1); // 将对象原本的C字符串拷贝过来(包括'\0')delete[] _str;_str = tmp;_capacity = n;}
}

在这里插入图片描述

resize

其规则:

  1. 当n大于当前的size时,将size扩大到n,扩大的字符为ch,若ch未给出,则默认为’\0’
  2. 当n小于当前的size时,将size缩小到n
void string::resize(size_t n, char ch = '\0')
{if (n < _size) // n小于当前size{_size = n; // 将size调整为n_str[_size] = '\0'; // 在size个字符后放上'\0'}else if (n > _capacity){reserve(n); // 扩容for (size_t i = _size; i < n; i++) // 将size扩大到n,扩大的字符为ch{_str[i] = ch;}_size = n; // size更新_str[_size] = '\0'; // 字符串后面放上'\0'}
}

empty

empty是string的判空函数

bool string::empty() const
{return _size == 0;
}

五、修改字符串相关函数

c_str

按照C语言的格式返回字符串

const char* string::c_str() const
{return _str;
}

push_back

push_back函数的作用就是在当前字符串的后面尾插上一个字符,尾插之前首先需要判断是否需要增容,若需要,则调用reserve函数进行增容,然后再尾插字符,注意尾插完字符后需要在该字符的后方设置上’\0’,否则打印字符串的时候会出现非法访问,因为尾插的字符后方不一定就是’\0’

void string::push_back(char ch)
{if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;++_size;_str[_size] = '\0';
}

append

append函数的作用是在当前字符串的后面尾插一个字符串,尾插前需要判断当前字符串的空间能否容纳下尾插后的字符串,若不能,则需要先进行增容,然后再将待尾插的字符串尾插到对象的后方,因为待尾插的字符串后方自身带有’\0’,所以我们无需再在后方设置’\0’

void string::append(const char* str)
{size_t len = strlen(str);if (_size + len > _capacity){// 大于2倍,需要多少开多少,小于2倍按2倍扩reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);}strcpy(_str + _size, str);_size += len;
}

operator+=

有三个重载:
string& operator+=(const string& str);
string& operator+=(const char* s);
string& operator+=(char c);

string& string::operator+=(char ch)
{push_back(ch);return *this;
}string& string::operator+=(const char* str)
{append(str);return *this;
}string& string::operator+=(const string& str)
{append(str.c_str());return *this;
}

insert

insert函数的作用是在字符串的任意位置插入字符或是字符串

// 插入字符,注意end不会为-1
void string::insert(size_t pos, char ch)
{assert(pos <= _size);// 谨慎使用if (_size == _capacity){size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newCapacity);}size_t end = _size;while (end >= pos) {_str[end + 1] = _str[end];if (end == 0) break; // end == -1 -> err--end;}_str[pos] = ch;++_size;
}

insert函数用于插入字符时,首先需要判断pos的合法性,若不合法则无法进行操作,紧接着还需判断当前对象能否容纳插入字符后的字符串,若不能则还需调用reserve函数进行扩容。插入字符的过程也是比较简单的,先将pos位置及其后面的字符统一向后挪动一位,给待插入的字符留出位置,然后将字符插入字符串即可
在这里插入图片描述

void string::insert(size_t pos, const char* str)
{assert(pos <= _size);size_t len = strlen(str);reserve(_size + len);size_t end = _size;while (end >= pos) {_str[end + len] = _str[end];if (end == 0) break; // end == -1 -> err--end;}memcpy(_str + pos, str, len);_size += len;
}

insert函数用于插入字符串时,首先也是判断pos的合法性,若不合法则无法进行操作,再判断当前对象能否容纳插入该字符串后的字符串,若不能则还需调用reserve函数进行扩容,插入字符串时,先将pos位置及其后面的字符统一向后挪动len位(len为待插入字符串的长度),给待插入的字符串留出位置,然后将其插入字符串即可
在这里插入图片描述

erase

先来关注函数原型:

默认从0位置开始,一直清楚到末尾
void erase(size_t pos = 0, size_t len = npos);

erase函数的作用是删除字符串任意位置开始的n个字符。删除字符前也需要判断pos的合法性,这时候一共有两种情况

  1. pos位置及其之后的有效字符都需要被删除

这时我们只需在pos位置放上’\0’,然后将对象的size更新即可
在这里插入图片描述

  1. pos位置及其之后的有效字符只需删除一部分

这时我们可以用后方需要保留的有效字符覆盖前方需要删除的有效字符,此时不用在字符串后方加’\0’,因为在此之前字符串末尾就有’\0’了
在这里插入图片描述

void string::erase(size_t pos, size_t len)
{assert(pos < _size);// 当len == npos时候,条件判断一定成立if (len >= _size - pos) {// pos后(含)全删完_str[pos] = '\0';_size = pos;}else {strcpy(_str + pos, _str + pos + len);_size -= len;}
}

clear

clear函数用于将对象中存储的字符串置空,实现时直接将对象的_size置空,然后在字符串后面放上’\0’即可

void string::clear()
{_str[0] = '\0';_size = 0;
}

swap

swap函数用于交换两个对象的数据,直接调用库里的swap模板函数将对象的各个成员变量进行交换即可

void string::swap(string& str)
{std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);
}

substr

substr功能是返回从指定位置开始len长度的字符串,先创建string空对象用于接收截取字符串,当len == npos 或len >= _size - pos,代表了从pos位置到尾的字符串截取,并且尽量书写 len >= _size - pos ,而不是 len + pos >= _size 这种,是为了防止 len + pos 超过类型最大值范围

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];}sub._size = len;return sub;}
}

六、访问字符串相关函数

operator[ ]

[ ]运算符的重载是为了让string对象能像C字符串一样,通过[ ] +下标的方式获取字符串对应位置的字符
这里要有两种版本,一种可读可写,一种只读不写

char& string::operator[](size_t pos) 
{assert(pos < _size);return _str[pos];
}const char& string::operator[](size_t pos) const
{assert(pos < _size);return _str[pos];
}

find

实现这两种重载:

size_t find(char ch, size_t pos = 0);
size_t find(const char* str, size_t pos = 0);

// 正向查找第一个匹配的字符
size_t string::find(char ch, size_t pos)
{assert(pos < _size); //检测下标的合法性for (size_t i = pos; i < _size; i++) {if (_str[i] == ch) {return i;}}return npos;
}// 正向查找第一个匹配的字符串
size_t string::find(const char* sub, size_t pos)
{assert(pos < _size); //检测下标的合法性char* p = strstr(_str + pos, sub);return p == NULL ? npos : p - _str;
}

  对于第一种,首先判断所给pos的合法性,然后通过遍历的方式从pos位置开始向后寻找目标字符,若找到,则返回其下标;若没有找到,则返回npos。(npos是string类的一个静态成员变量其值为整型最大值

  对于第二种,首先也是先判断所给pos的合法性,然后我们可以通过调用strstr函数进行查找。strstr函数若是找到了目标字符串会返回字符串的起始位置,若是没有找到会返回一个C语言空指针NULL,若是找到了目标字符串,我们可以通过计算目标字符串的起始位置和对象C字符串的起始位置的差值,进而得到目标字符串起始位置的下标

七、关系运算符重载函数

  关系运算符有 >、>=、<、<=、==、!= 这六个,但是对于C++中任意一个类的关系运算符重载,我们均只需重载其中的两个,剩下的四个关系运算符可以通过复用已经重载好了的两个关系运算符来实现

bool string::operator<(const string& s) const
{return strcmp(_str, s._str) < 0;
}bool string::operator>(const string& s) const
{return !(*this <= s);
}bool string::operator<=(const string& s) const
{return (*this == s || *this < s);
}bool string::operator>=(const string& s) const
{return !(*this < s);
}bool string::operator==(const string& s) const
{return strcmp(_str, s._str) == 0;
}bool string::operator!=(const string& s) const
{return !(*this == s);
}

八、 流插入与流提取

流插入

重载>>运算符是为了让string对象能够像内置类型一样使用>>运算符直接输入
输入前我们需要先将对象的C字符串置空,然后从标准输入流读取字符,直到读取到’ ‘或是’\n’便停止读取
另外还有,很明显得重载为全局函数

istream& operator>>(istream& is, string& str)
{str.clear(); // 要覆盖先前的内容,先清除一下char ch = is.get();//is >> ch; // 拿不到空格和换行while (ch != ' ' && ch != '\n') {str += ch;ch = is.get();}return is;
}

流提取

重载<<运算符是为了让string对象能够像内置类型一样使用<<运算符直接输出打印。实现时我们可以直接使用范围for对对象进行遍历即可

ostream& operator<<(ostream& os, const string& str)
{for (size_t i = 0; i < str.size(); i++) {os << str[i];}return os;
}

getline

getline函数用于读取一行含有空格的字符串。实现时于>>运算符的重载基本相同,只是当读取到’\n’的时候才停止读取字符

// 举个例子哈
int main()
{string str;cin >> str; // 假设输入hello worldcout << str; // 只会输出helloreturn 0;
}

如上,我们会发现空格字符无法被插入str,这时候就是getline发挥的时候了
再来道具体的题目,说不定能让你有更深的认识
在这里插入图片描述


总结

  总算是补上了!可以看出string类的完整实现还是蛮复杂的

相关文章:

Cpp::STL—string类的模拟实现(12)

文章目录 前言一、string类各函数接口总览二、默认构造函数string(const char* str "");string(const string& str);传统拷贝写法现代拷贝写法 string& operator(const string& str);传统赋值构造现代赋值构造 ~string(); 三、迭代器相关函数begin &…...

一文搞懂SentencePiece的使用

目录 1. 什么是 SentencePiece&#xff1f;2. SentencePiece 基础概念2.1 SentencePiece 的工作原理2.2 SentencePiece 的优点 3. SentencePiece 的使用3.1 安装 SentencePiece3.2 训练模型与加载模型3.3 encode&#xff08;高频&#xff09;3.4 decode&#xff08;高频&#x…...

一个简单的摄像头应用程序1

这个Python脚本实现了一个基于OpenCV的简单摄像头应用,我们在原有的基础上增加了录制视频等功能,用户可以通过该应用进行拍照、录制视频,并查看已拍摄的照片。以下是该脚本的主要功能和一些使用时需要注意的事项: 功能 拍照: 用户可以通过点击界面上的“拍照”按钮或按…...

通过PHP获取商品详情

在电子商务的浪潮中&#xff0c;数据的重要性不言而喻。商品详情信息对于电商运营者来说尤为宝贵。PHP&#xff0c;作为一种广泛应用的服务器端脚本语言&#xff0c;为我们提供了获取商品详情的便捷途径。 了解API接口文档 开放平台提供了详细的API接口文档。你需要熟悉商品详…...

【Android】获取备案所需的公钥以及签名MD5值

目录 重要前提 获取签名MD5值 获取公钥 重要前提 生成jks文件以及gradle配置应用该文件。具体步骤请参考我这篇文章&#xff1a;【Android】配置Gradle打包apk的环境_generate signed bundle or apk-CSDN博客 你只需要从头看到该文章的配置build.gradle&#xff08;app&…...

看480p、720p、1080p、2k、4k、视频一般需要多大带宽呢?

看视频都喜欢看高清,那么一般来说看电影不卡顿需要多大带宽呢? 以4K为例,这里引用一位网友的回答:“视频分辨率4092*2160,每个像素用红蓝绿三个256色(8bit)的数据表示,视频帧数为60fps,那么一秒钟画面的数据量是:4096*2160*3*8*60≈11.9Gbps。此外声音大概是视频数据量…...

解决IDEA中@Autowired红色报错的实用指南:原因与解决方案

前言&#xff1a; 在使用Spring Boot开发时&#xff0c;Autowired注解是实现依赖注入的常用方式。然而&#xff0c;许多开发者在IDEA中使用Autowired时&#xff0c;可能会遇到红色报错&#xff0c;导致代码的可读性降低。本文将探讨导致这种现象的原因&#xff0c;并提供几种解…...

408知识点自检(一)

一、细节题 虚电路是面向连接的吗&#xff1f;虚电路线路上会不会有其他虚电路通过&#xff1f;虚电路适合什么类型的数据交换&#xff1f;虚电路的可靠性靠其他协议还是自己&#xff1f;固态硬盘的优势体现在什么存取方式&#xff1f;中断向量地址是谁的地址&#xff1f;多播…...

负载均衡--相关面试题(六)

在负载均衡的面试中&#xff0c;可能会遇到一系列涉及概念、原理、实践应用以及技术细节的问题。以下是一些常见的负载均衡面试题及其详细解答&#xff1a; 一、什么是负载均衡&#xff1f; 回答&#xff1a;负载均衡是一种将网络请求或数据传输工作分配给多个服务器或网络资源…...

【Unity踩坑】Unity更新Google Play结算库

一、问题描述&#xff1a; 在Google Play上提交了app bundle后&#xff0c;提示如下错误。 我使用的是Unity 2022.01.20f1&#xff0c;看来用的Play结算库版本是4.0 查了一下文档&#xff0c;Google Play结算库的维护周期是两年。现在需要更新到至少6.0。 二、更新过程 1. 下…...

Redis:hash类型

Redis&#xff1a;hash类型 hash命令设置与读取HSETHGETHMGET 哈希操作HEXISTSHDELHKEYSHVALSHGETALLHLENHSETNXHINCRBYHINCRBYFLOAT 内部编码ziplisthashtable 目前主流的编程语言中&#xff0c;几乎都提供了哈希表相关的容器&#xff0c;Redis自然也会支持对应的内容&#xf…...

力扣9.30

1749. 任意子数组和的绝对值的最大值 给你一个整数数组 nums 。一个子数组 [numsl, numsl1, ..., numsr-1, numsr] 的 和的绝对值 为 abs(numsl numsl1 ... numsr-1 numsr) 。 请你找出 nums 中 和的绝对值 最大的任意子数组&#xff08;可能为空&#xff09;&#xff0c…...

kafka下载配置

下载安装 参开kafka社区 zookeeperkafka消息队列群集部署https://apache.csdn.net/66c958fb10164416336632c3.html 下载 kafka_2.12-3.2.0安装包快速下载地址分享 官网下载链接地址&#xff1a; 官网下载地址&#xff1a;https://kafka.apache.org/downloads 官网呢下载慢…...

nlp任务之预测中间词-huggingface

目录 1.加载编码器 1.1编码试算 2.加载数据集 3.数据集处理 3.1 map映射&#xff1a;只对数据集中的sentence数据进行编码 3.2用filter()过滤 单词太少的句子过滤掉 3.3截断句子 4.创建数据加载器Dataloader 5. 下游任务模型 6.测试预测代码 7.训练代码 8.保…...

《程序猿之Redis缓存实战 · Redis 与数据库一致性》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

【无标题】observer: error while loading shared libraries: libmariadb.so.3处理办法

文章目录 1.记录新装的oceanbase,使用observer帮助时&#xff0c;出现lib文件无法找到的处理过程 ./observer --help ./observer: error while loading shared libraries: libmariadb.so.3: cannot open shared object file: No such file or directory2.做一个strace跟踪&…...

极客兔兔Gee-Cache Day1

极客兔兔7Days GeeCache - Day1 interface{}&#xff1a;任意类型 缓存击穿&#xff1a;一个高并发的请求查询一个缓存中不存在的数据项&#xff0c;因此这个请求穿透缓存直接到达后端数据库或数据源来获取数据。如果这种请求非常频繁&#xff0c;就会导致后端系统的负载突然…...

[MAUI]数据绑定和MVVM:MVVM的属性验证

一、MVVM的属性验证案例 Toolkit.Mvvm框架中的ObservableValidator类,提供了属性验证功能,可以使用我们熟悉的验证特性对属性的值进行验证,并将错误属性提取和反馈给UI层。以下案例实现对UI层的姓名和年龄两个输入框,进行表单提交验证。实现效果如下所示 View<ContentP…...

2024年水利水电安全员考试题库及答案

一、判断题 1.采用水下钻孔爆破方案时&#xff0c;侧面应采用预裂爆破&#xff0c;并严格控制单响药量以保护附近建&#xff08;构&#xff09;筑物的安全。 答案&#xff1a;正确 2.围堰爆破拆除工程的实施应成立爆破指挥机构&#xff0c;并应按设计确定的安全距离设置警戒。…...

【快速删除 node_modules 】rimraf

目录 1. 什么是node_modules 2. 卸载一个npm包 3. 删除 node_modules 为什么这么慢 4. rimraf 5. 为什么rimraf 这么快 作为前端开发&#xff0c;无论我们关注不关注&#xff0c;每天都能接触到node_modules。通常产生于一个npm install命令&#xff0c;之后就不会多加关注…...

毕业设计选题:基于ssm+vue+uniapp的教学辅助小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…...

13-指针和动态内存-内存泄漏

一、视频笔记&#xff1a; C语言通过malloc&#xff0c;来获取堆上的内存。 动态调用内存&#xff1a; malloc 和 free &#xff1b;new 和 delete 都行。 内存泄漏指的是我们动态申请了内存&#xff0c;但是即是是使用完了之后&#xff08;从来都不去释放它&#xff09;。只…...

基于深度学习的视频摘要生成

基于深度学习的视频摘要生成是一种通过自动化方式从长视频中提取关键片段&#xff0c;生成简洁且有代表性的视频摘要的技术。其目的是在保留视频主要内容的基础上&#xff0c;大幅缩短视频的播放时长&#xff0c;方便用户快速理解视频的核心信息。以下是视频摘要生成的主要方法…...

适合初学者的[JAVA]: 基础面试题

目录 说明 前言 String/StringBuffer/StringBuilder区别 第一点: 第二点: 总结&#xff1a; 反射机制 JVM内存结构 运行时数据区域被划分为5个主要组件&#xff1a; 方法区&#xff08;Method Area&#xff09; 堆区&#xff08;Heap Area&#xff09; 栈区&#x…...

internal.KaptWithoutKotlincTask$KaptExecutionWorkAction 问题 ---Room数据库

Caused by: java.lang.Exception: No native library is found for os.nameMac and os.archaarch64. path/org/sqlite/native/Mac/aarch64 m3 目前使用的是MAC M3芯片的配置会出现这个问题。M1就应该就有这个问题 解决&#xff1a; 在project层级的build.gradle中的allprojec…...

Frequency-aware Feature Fusion for Dense Image Prediction 论文阅读

摘要:密集图像预测任务要求具有强类别信息和高分辨率精确空间边界细节的特征。为了实现这一点&#xff0c;现代分层模型通常利用特征融合&#xff0c;直接添加来自深层的上采样粗特征和来自较低层次的高分辨率特征。在本文中&#xff0c;我们观察到融合特征值在对象内的快速变化…...

Springboot + netty + rabbitmq + myBatis

目录 0.为什么用消息队列1.代码文件创建结构2.pom.xml文件3.三个配置文件开发和生产环境4.Rabbitmq 基础配置类 TtlQueueConfig5.建立netty服务器 rabbitmq消息生产者6.建立常规队列的消费者 Consumer7.建立死信队列的消费者 DeadLetterConsumer8.建立mapper.xml文件9.建立map…...

电磁兼容(EMC):整改案例(四)人体对EFT测试影响有多大?

目录 1. 异常现象 2. 原因分析 3. 整改方案 4. 总结 1. 异常现象 某产品按GB/T 17626.4标准进行电快速瞬变脉冲群测试&#xff0c;测试条件为&#xff1a;频率5kHz/100kHz&#xff0c;测试电压L&#xff0c;N线间2kV&#xff0c;L&#xff0c;N线对PE线4kV。测试过程中需要…...

数据可视化基础:让数据说话

一、引言 在信息洪流中&#xff0c;数据可视化如同灯塔&#xff0c;照亮了数据的海洋&#xff0c;让我们能够洞察数据背后的意 义。 下面是对数据可视化的详细介绍&#xff0c;包括定义、作用、类型、原则、工具方法以及应用场景&#xff0c; 并附上具体的代码示例。 二、数…...

有哪些优化数据库性能的方法?如何定位慢查询?数据库性能优化全攻略:从慢查询定位到高效提升

在现代应用程序开发中&#xff0c;数据库的性能对于整体系统的响应能力至关重要。随着用户数量的增加和数据量的增长&#xff0c;如何优化数据库性能、定位慢查询成了每一个开发者面临的重要挑战。今天&#xff0c;我想和大家分享一些实用的数据库性能优化方法&#xff0c;以及…...

莆田网站建设技术托管/外链发布

大数据时代来了&#xff01;不得不承认如今数据量的激增越来越明显&#xff0c;各种各样的数据铺天盖地的砸下来&#xff0c;企业选择相应工具来存储、分析与处理它们。从Excel、BI工具&#xff0c;到现在最新的可视化数据分析工具大数据魔镜&#xff0c;数据分析软件进步越来越…...

wordpress手机app编辑文章/seo精华网站

今天这篇文章送给产品经理或想成为产品经理的读者们&#xff01;通过阅读&#xff0c;我积累了大量的产品知识&#xff1b;通过写作&#xff0c;我链接到了亲爱的读者们&#xff0c;有机会将工作、职场的感悟分享给大家&#xff01;要说这个时代&#xff0c;什么最难能可贵&…...

徐州整站优化/刷外链网站

有的时候当杀毒软件处理完病毒程序后&#xff0c;会造成双击硬盘盘符打不开、右击出现等AUTO字样等&#xff0c;殊不知此类情况的发生跟系统主录下的配置文件autorun.inf有关。 解读autorun.inf由于计算机在系统运行时会自动搜索盘符目录下的Autorun.inf配置文件&#xff0c;并…...

dw制作简单网站/自己的网站怎么建立

Supervisor是一个进程监控程序。 需求一&#xff1a;我现在有一个进程需要每时每刻不断的跑&#xff0c;但是这个进程又有可能由于各种原因有可能中断。当进程中断的时候我希望能自动重新启动它&#xff0c;此时&#xff0c;我就需要使用到了Supervisor 先弄懂两个命令: superv…...

layui做网站前端/百度竞价开户联系方式

首先说一下&#xff0c;如果大家喜欢可直接收藏我这个项目的github地址。https://github.com/951565664/... 因为有可能github上版本更新了&#xff0c;但是这边就不更新了。如果有什么问题&#xff0c;可以随时问&#xff0c;建议不要QQ或者私信&#xff0c;直接上github提iss…...

做网站的视频教学/免费b站推广网站2022

https://software.broadinstitute.org/morpheus/转载于:https://www.cnblogs.com/0820LL/p/11163564.html...