string_view学习笔记

前言

  1. 将对string_view称呼为sv

1 string_view概述

sv对象不拥有数据,只是对数据的引用。因此,对sv对象有两点限制:

  1. 不允许修改sv对象内部的数据
  2. sv对象引用的数据要有足够长的生命周期

string_view类只声明了两个私有成员,如下:

      size_t	    _M_len; //字符串的长度,不一定是strlen(_M_str)
      const _CharT* _M_str; //对字符串的引用,通过指针去访问,并没有开辟一个新的数组

2 string_view使用

1 constructor

  • 无参构造
	  constexpr      
      basic_string_view() noexcept 
      : _M_len{0}, _M_str{nullptr} 
      { }
  • 使用字符串字面量构造

注意:字符串中间插入null字符,会对字符串进行截取

	   __attribute__((__nonnull__)) constexpr           
      basic_string_view(const _CharT* __str) noexcept
      : _M_len{traits_type::length(__str)},
	_M_str{__str}
  • 使用字符串字面量 + 指定长度构造

注意:可以解决这个问题

      constexpr 
      basic_string_view(const _CharT* __str, size_type __len) noexcept
      : _M_len{__len}, _M_str{__str}
      { }
  • 使用迭代区间构造

注意to_address内部有一个静态断言,如果_first为函数指针,会发生错误

	constexpr    
	basic_string_view(_It __first, _End __last)
	noexcept(noexcept(__last - __first))
	: _M_len(__last - __first), _M_str(std::to_address(__first))
	{ }

2 remove_prefix, remove_suffix

移除指定长度的前缀和后缀

      constexpr void 
      remove_prefix(size_type __n) noexcept
      {
	__glibcxx_assert(this->_M_len >= __n);
	this->_M_str += __n;
	this->_M_len -= __n;
      }

      constexpr void
      remove_suffix(size_type __n) noexcept
      { this->_M_len -= __n; }

3 copy

从sv对象引用字符串的__pos位置开始,拷贝n个字符到__str字符数组中,返回实际拷贝的字符数

注意:由于标准库内部做了优化操作,如果你想拷贝从某个字符起始的所有字符,__n可以取最大

      size_type                     
      copy(_CharT* __str, size_type __n, size_type __pos = 0) const
      {
	__glibcxx_requires_string_len(__str, __n); // 要求__str字符数组的长度大于等于__n
	__pos = std::__sv_check(size(), __pos, "basic_string_view::copy");  //检查sv对象中__pos位置是否存在,也就是比较size()和__pos的大小
	const size_type __rlen = std::min(__n, _M_len - __pos); //要拷贝字符的个数。标准库内部的优化操作,防止拷贝是越界
	// _GLIBCXX_RESOLVE_LIB_DEFECTS
	// 2777. basic_string_view::copy should use char_traits::copy
	traits_type::copy(__str, data() + __pos, __rlen); 
	return __rlen;
      }

4 substr

获取从某个位置起始,指定长度的,string_view对象

      constexpr basic_string_view          
      substr(size_type __pos = 0, size_type __n = npos) const noexcept(false) 
      { //npos 是unsigned long类型,值为-1,也就是数值最大
	__pos = std::__sv_check(size(), __pos, "basic_string_view::substr"); 
	const size_type __rlen = std::min(__n, _M_len - __pos); 
	return basic_string_view{_M_str + __pos, __rlen}; 
      }

5 starts_with, ends_with

1 starts_with

检查sv对象是否以某一个字符或字符串为前缀

      constexpr bool   
      starts_with(basic_string_view __x) const noexcept
      { return this->substr(0, __x.size()) == __x; }

      constexpr bool
      starts_with(_CharT __x) const noexcept
      { return !this->empty() && traits_type::eq(this->front(), __x); }

      constexpr bool
      starts_with(const _CharT* __x) const noexcept
      { return this->starts_with(basic_string_view(__x)); }

2 ends_with

检查sv对象是否以某一个字符或字符串为后缀

      constexpr bool    
      ends_with(basic_string_view __x) const noexcept
      {
	const auto __len = this->size();
	const auto __xlen = __x.size();
	return __len >= __xlen
	  && traits_type::compare(end() - __xlen, __x.data(), __xlen) == 0;
      }

      constexpr bool
      ends_with(_CharT __x) const noexcept
      { return !this->empty() && traits_type::eq(this->back(), __x); }

      constexpr bool
      ends_with(const _CharT* __x) const noexcept
      { return this->ends_with(basic_string_view(__x)); }

6 find和rfind

在sv对象中查找某一个字符或字符串

说明__pos是sv对象内查找的起始位置,__str目标字符串,__c查找的字符,__n目标字符串的长度

      constexpr size_type
      find(basic_string_view __str, size_type __pos = 0) const noexcept
      { return this->find(__str._M_str, __pos, __str._M_len); }

      constexpr size_type
      find(_CharT __c, size_type __pos = 0) const noexcept;

      constexpr size_type
      find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;

      __attribute__((__nonnull__)) constexpr size_type
      find(const _CharT* __str, size_type __pos = 0) const noexcept
      { return this->find(__str, __pos, traits_type::length(__str)); 

rfind类似,不做解释

7 find_first_of, find_last_of, find_first_not_of, find_last_not_of

这里解释第一个find_first_of。在源字符串视图中,目标字符串字符集合中字符出现的第一个位置

参数和find类似

      constexpr size_type
      find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
      { return this->find_first_of(__str._M_str, __pos, __str._M_len); }

      constexpr size_type
      find_first_of(_CharT __c, size_type __pos = 0) const noexcept
      { return this->find(__c, __pos); }

      constexpr size_type
      find_first_of(const _CharT* __str, size_type __pos,
		    size_type __n) const noexcept;

      __attribute__((__nonnull__)) constexpr size_type
      find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
      { return this->find_first_of(__str, __pos, traits_type::length(__str)); }

其他类似

8 对sv对象的比较

  1. 使用简单的比较运算符
  2. sv类重载了三路运算符,使用三路运算符比较
  3. 使用compare成员函数比较

1 简单比较运算符

    std::string_view strView = "world!";
    std::string_view charsToExclude = "world!";
    
    if (strView < charsToExclude) std::cout << "小于" << std::endl;
    else if (strView > charsToExclude) std::cout << "大于" << std::endl; 
    else if (strView == charsToExclude) std::cout << "等于" << std::endl;

2 三路运算符

    auto result = strView <=> charsToExclude;
    if (std::is_lt(result)) std::cout << "小于" << std::endl;
    else if (result == std::partial_ordering::greater) std::cout << "大于" << std::endl; 
    else if (result == std::partial_ordering::equivalent) std::cout << "等于" << std::endl;

3 compare

    int res = strView.compare(charsToExclude);
    if (res < 0) std::cout << "小于" << std::endl;
    else if (res > 0) std::cout << "大于" << std::endl; 
    else if (res == 0) std::cout << "等于" << std::endl;

其他简单方法

1 size,length

获取引用字符串的长度

      constexpr size_type     
      size() const noexcept
      { return this->_M_len; }

      constexpr size_type
      length() const noexcept
      { return _M_len; }

2 empty

判断是否为空

      [[nodiscard]] constexpr bool
      empty() const noexcept
      { return this->_M_len == 0; }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值