前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C++】STL——string

【C++】STL——string

作者头像
用户11290673
发布2024-09-25 13:13:30
700
发布2024-09-25 13:13:30
举报
文章被收录于专栏:学习

前言 本篇博客我们来看一下C++标准库里STL库中将字符串相关属性自定义成string类,并且标准库里给出很多关于string的库函数,我们一起来了解一下string 💓 个人主页:小张同学zkf ⏩ 文章专栏:C++ 若有问题 评论区见📝 🎉欢迎大家点赞👍收藏⭐文章 ​

1. string类介绍

1.1string

链接:string类介绍

使用 string 类时,必须包含 #include 头文件以及 using namespace std ;

1.2auto和范围for

auto 关键字

在早期 C/C++ 中 auto 的含义是:使用 auto 修饰的变量,是具有自动存储器的局部变量,后来这个 不重要了。 C++11 中,标准委员会变废为宝赋予了 auto 全新的含义即: auto 不再是一个存储类型 指示符,而是作为一个新的类型指示符来指示编译器, auto 声明的变量必须由编译器在编译时期 推导而得 auto 声明指针类型时,用 auto auto* 没有任何区别,但用 auto 声明引用类型时则必须加 & 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际 只对第一个类型进行推导,然后用推导出来的类型定义其他变量auto 不能作为函数的参数,可以做返回值,但是建议谨慎使用 auto 不能直接用来声明数组

举个例子

#include<iostream> using namespace std ; int func1 () { return 10 ; } // 不能做参数 void func2 ( auto a ) {} // 可以做返回值,但是建议谨慎使用 auto func3 () { return 3 ; } int main () { int a = 10 ; auto b = a ; auto c = 'a' ; auto d = func1 (); // 编译报错 :rror C3531: “e”: 类型包含 “auto” 的符号必须具有初始值设定项 auto e ; 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 ; auto aa = 1 , bb = 2 ; // 编译报错: error C3538: 在声明符列表中, “auto” 必须始终推导为同一类型 auto cc = 3 , dd = 4.0 ; // 编译报错: error C3318: “auto []”: 数组不能具有其中包含 “auto” 的元素类型 auto array [] = { 4 , 5 , 6 }; return 0 ; }

范围for

对于一个 有范围的集合 而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的 for 循环。 for 循环后的括号由冒号 分为两部分:第一部分是范围 内用于迭代的变量,第二部分则表示被迭代的范围 ,自动迭代,自动取数据,自动判断结束。 范围for 可以作用到数组和容器对象上进行遍历范围for 的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。

举个例子

#include<iostream> #include <string> #include <map> using namespace std ; int main () { int array [] = { 1 , 2 , 3 , 4 , 5 }; // C++98 的遍历 for ( int i = 0 ; i < sizeof ( array ) / sizeof ( array [ 0 ]); ++ i ) { array [ i ] *= 2 ; } for ( int i = 0 ; i < sizeof ( array ) / sizeof ( array [ 0 ]); ++ i ) { cout << array [ i ] << endl ; } // C++11 的遍历 for ( auto & e : array ) e *= 2 ; for ( auto e : array ) cout << e << " " << endl ; string str ( "hello world" ); for ( auto ch : str ) { cout << ch << " " ; } cout << endl ; return 0 ; }


2.string类的常用接口

2.1string的常见构造

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


2.2string类对象的容量操作

注意: 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 不会改变容量大小。


2.3string类对象的访问及遍历操作


2.4string类对象的修改操作

注意: 1. 在 string 尾部追加字符时, s.push_back(c) / s.append(1, c) / s += 'c' 三种的实现方式差 不多,一般情况下 string 类的 += 操作用的比较多, += 操作不仅可以连接单个字符,还可 以连接字符串。 2. 对 string 操作时,如果能够大概预估到放多少字符,可以先通过 reserve 把空间预留 好。


2.5string类非成员函数

string 类中还有一些其他的操作,这里不一一列举,大家在需要用到时不明白了查文档即可。


3.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 ); }

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

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来 。如果 对象中管理资源 ,最后就会 导致 多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该 资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规 。 就像一个家庭中有两个孩子,但父母只买了一份玩具,两个孩子愿意一块玩,则万事大吉,万一不想分享就你争我夺,玩具损坏。

可以采用深拷贝解决浅拷贝问题,即: 每个对象都有一份独立的资源,不要和其他对象共享 。父母给每个孩子都买一份玩具,各自玩各自的就不会有问题了。

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

传统写法的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 ( new char [ strlen ( s . _str ) + 1 ]) { strcpy ( _str , s . _str ); } 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 = nullptr ; } } private : char* _str ; }

现代写法的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 ; };

结束语 STL——string的相关知识总结完了,下一篇我们总结STL里的vector OK,感谢观看!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. string类介绍
    • 1.1string
      • 1.2auto和范围for
      • 2.string类的常用接口
        • 2.1string的常见构造
          • 2.2string类对象的容量操作
            • 2.3string类对象的访问及遍历操作
              • 2.4string类对象的修改操作
                • 2.5string类非成员函数
                • 3.string类的模拟实现
                相关产品与服务
                容器服务
                腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档