C++ 基础: std::string

这篇具有很好参考价值的文章主要介绍了C++ 基础: std::string。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、常见的使用

std::string是C++标准库中的一个类,用于表示可变长度的字符串。它是由字符类型(通常是char)的数组实现的,并提供了许多字符串操作函数。

std::string的构造函数有多种形式,可以用于初始化空字符串、从字符数组或另一个字符串中复制字符串、从指定长度的字符数组或另一个字符串中截取字符串等。例如:

// 初始化空字符串
std::string str1;

// 从字符数组中复制字符串
char chars[] = "Hello, world!";
std::string str2(chars);

// 从另一个字符串中复制字符串
std::string str3(str2);

// 截取另一个字符串中的一部分
std::string str4(str2, 7, 5);

std::string重载了许多运算符,使得字符串的处理更加方便。例如,可以使用"+“运算符将两个字符串连接起来,也可以使用”==“、”<"等运算符比较两个字符串是否相等或大小关系。

std::string还提供了许多成员函数,用于操作字符串。以下是一些常用的成员函数:

length() 和 size(): 返回字符串的长度。
clear(): 清空字符串。
empty(): 如果字符串为空,则返回true。
append(): 在字符串末尾添加字符串或字符。
substr(): 返回从字符串中的指定位置开始的指定长度的子字符串。
replace(): 用另一个字符串或字符替换字符串中的一段子字符串。
find(): 查找字符串中第一个出现指定子字符串的位置。
rfind(): 查找字符串中最后一个出现指定子字符串的位置。
compare(): 将字符串与另一个字符串或字符进行比较。

除了这些成员函数外,std::string还可以像普通字符数组一样直接操作,例如使用下标访问字符串中的字符。此外,它还支持使用迭代器来遍历字符串中的字符。

需要注意的是,在使用std::string时,通常应该使用std::string::size_type类型来表示字符串的长度,而不是使用int类型。这是因为std::string可能包含大量数据,超出了int类型的表示范围。

总之,std::string提供了方便的字符串操作方法,是C++中常用的字符串类型。

示例

字符串初始化:

std::string str;               // 创建一个空字符串
std::string str("hello");      // 创建一个包含 "hello" 的字符串
std::string str = "world";     // 同上

字符串连接:

std::string str1 = "hello";
std::string str2 = "world";
std::string str3 = str1 + ", " + str2;   // str3 等于 "hello, world"

字符串比较:

std::string str1 = "apple";
std::string str2 = "banana";
if (str1 == str2) {
    // 相等
} else if (str1 < str2) {
    // str1 小于 str2
} else {
    // str1 大于 str2
}

获取字符串长度:

std::string str = "hello, world";
int len = str.length();   // len 等于 12

获取子字符串:

std::string str = "hello, world";
std::string sub_str = str.substr(0, 5);   // sub_str 等于 "hello"

查找子字符串:

std::string str = "hello, world";
size_t pos = str.find("world");    // pos 等于 7

剖析

using string  = basic_string<char, char_traits<char>, allocator<char>>;
using wstring = basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>;

string 其实是basic_string 类型的模板特化。文章来源地址https://www.toymoban.com/news/detail-684944.html

template <class _Elem, class _Traits = char_traits<_Elem>, class _Alloc = allocator<_Elem>>
class basic_string { // null-terminated transparent array of elements
private:
    friend _Tidy_deallocate_guard<basic_string>;
    friend basic_stringbuf<_Elem, _Traits, _Alloc>;

    using _Alty        = _Rebind_alloc_t<_Alloc, _Elem>;
    using _Alty_traits = allocator_traits<_Alty>;

    using _Scary_val = _String_val<conditional_t<_Is_simple_alloc_v<_Alty>, _Simple_types<_Elem>,
        _String_iter_types<_Elem, typename _Alty_traits::size_type, typename _Alty_traits::difference_type,
            typename _Alty_traits::pointer, typename _Alty_traits::const_pointer, _Elem&, const _Elem&>>>;

    static_assert(!_ENFORCE_MATCHING_ALLOCATORS || is_same_v<_Elem, typename _Alloc::value_type>,
        _MISMATCHED_ALLOCATOR_MESSAGE("basic_string<T, Traits, Allocator>", "T"));

    static_assert(is_same_v<_Elem, typename _Traits::char_type>,
        "N4910 23.4.3.2 [string.require]/3 requires that the supplied "
        "char_traits character type match the string's character type.");

    static_assert(!is_array_v<_Elem> && is_trivial_v<_Elem> && is_standard_layout_v<_Elem>,
        "The character type of basic_string must be a non-array trivial standard-layout type. See N4910 "
        "23.1 [strings.general]/1.");

public:
    using traits_type    = _Traits;
    using allocator_type = _Alloc;

    using value_type      = _Elem;
    using size_type       = typename _Alty_traits::size_type;
    using difference_type = typename _Alty_traits::difference_type;
    using pointer         = typename _Alty_traits::pointer;
    using const_pointer   = typename _Alty_traits::const_pointer;
    using reference       = value_type&;
    using const_reference = const value_type&;

    using iterator       = _String_iterator<_Scary_val>;
    using const_iterator = _String_const_iterator<_Scary_val>;

    using reverse_iterator       = _STD reverse_iterator<iterator>;
    using const_reverse_iterator = _STD reverse_iterator<const_iterator>;

private:
    static constexpr auto _BUF_SIZE   = _Scary_val::_BUF_SIZE;
    static constexpr auto _ALLOC_MASK = _Scary_val::_ALLOC_MASK;

    // When doing _String_val operations by memcpy, we are touching:
    //   _String_val::_Bx::_Buf (type is array of _Elem)
    //   _String_val::_Bx::_Ptr (type is pointer)
    //   _String_val::_Mysize   (type is size_type)
    //   _String_val::_Myres    (type is size_type)
    // N4910 23.1 [strings.general]/1 says _Elem must be trivial standard-layout, so memcpy is safe.
    // We need to ask if pointer is safe to memcpy.
    // size_type must be an unsigned integral type so memcpy is safe.
    // We also need to disable memcpy if the user has supplied _Traits, since
    //   they can observe traits::assign and similar.
    static constexpr bool _Can_memcpy_val = _Is_specialization_v<_Traits, char_traits> && is_trivial_v<pointer>;
    // This offset skips over the _Container_base members, if any
    static constexpr size_t _Memcpy_val_offset = _Size_after_ebco_v<_Container_base>;
    static constexpr size_t _Memcpy_val_size   = sizeof(_Scary_val) - _Memcpy_val_offset;

    template <class _Iter>
    // TRANSITION, /clr:pure is incompatible with templated static constexpr data members
    // static constexpr bool _Is_elem_cptr =_Is_any_of_v<_Iter, const _Elem* const, _Elem* const, const _Elem*, _Elem*>;
    using _Is_elem_cptr = bool_constant<_Is_any_of_v<_Iter, const _Elem* const, _Elem* const, const _Elem*, _Elem*>>;

#if _HAS_CXX17
    template <class _StringViewIsh>
    using _Is_string_view_ish =
        enable_if_t<conjunction_v<is_convertible<const _StringViewIsh&, basic_string_view<_Elem, _Traits>>,
                        negation<is_convertible<const _StringViewIsh&, const _Elem*>>>,
            int>;
#endif // _HAS_CXX17

#ifdef _INSERT_STRING_ANNOTATION
    _CONSTEXPR20 void _Create_annotation() const noexcept {
        // Annotates the valid range with shadow memory
        auto& _My_data = _Mypair._Myval2;
        _Apply_annotation(_My_data._Myptr(), _My_data._Myres, _My_data._Myres, _My_data._Mysize);
    }

    _CONSTEXPR20 void _Remove_annotation() const noexcept {
        // Removes annotation of the range with shadow memory
        auto& _My_data = _Mypair._Myval2;
        _Apply_annotation(_My_data._Myptr(), _My_data._Myres, _My_data._Mysize, _My_data._Myres);
    }

    _CONSTEXPR20 void _Modify_annotation(const difference_type _Count) const noexcept {
        // Extends/shrinks the annotated range by _Count
        if (_Count == 0) {
            return;
        }

        auto& _My_data = _Mypair._Myval2;
        _Apply_annotation(
            _My_data._Myptr(), _My_data._Myres, _My_data._Mysize, static_cast<size_type>(_My_data._Mysize + _Count));
    }

    _NODISCARD static const void* _Get_aligned_first(const void* _First, const size_type _Capacity) noexcept {
        const char* _CFirst = reinterpret_cast<const char*>(_First);

        if (_Capacity >= _Asan_granularity) { // We are guaranteed to have sufficient space to find an aligned address
            return reinterpret_cast<const void*>(
                (reinterpret_cast<uintptr_t>(_CFirst) + (_Asan_granularity - 1)) & ~(_Asan_granularity - 1));
        }

        uintptr_t _Alignment_offset = reinterpret_cast<uintptr_t>(_CFirst) & (_Asan_granularity - 1);
        if (_Alignment_offset != 0) {
            _Alignment_offset = _Asan_granularity - _Alignment_offset;
        }

        if (_Capacity > _Alignment_offset) {
            return _CFirst + _Alignment_offset;
        }

        return nullptr;
    }

    static _CONSTEXPR20 void _Apply_annotation(const value_type* _Ptr, const size_type _Capacity,
        const size_type _Old_size, const size_type _New_size) noexcept {
#if _HAS_CXX20
        if (_STD is_constant_evaluated()) {
            return;
        }
#endif // _HAS_CXX20

        if (!_Asan_string_should_annotate) {
            return;
        }

        // We need to check whether we have a misaligned SSO buffer because of the proxy in `_Container_base` (e.g. x86)
        if constexpr (_Memcpy_val_offset % _Asan_granularity != 0) {
            const uintptr_t _Alignment_offset = reinterpret_cast<uintptr_t>(_Ptr) & (_Asan_granularity - 1);
            if (_Alignment_offset != 0 && _Capacity == _BUF_SIZE - 1) {
                return;
            }
        }

        // Needs to consider the null terminator
        const char* _First    = reinterpret_cast<const char*>(_Ptr);
        const char* _End      = reinterpret_cast<const char*>(_Ptr + _Capacity + 1);
        const char* _Old_last = reinterpret_cast<const char*>(_Ptr + _Old_size + 1);
        const char* _New_last = reinterpret_cast<const char*>(_Ptr + _New_size + 1);
        if constexpr (_Has_minimum_allocation_alignment_string<basic_string>) {
            __sanitizer_annotate_contiguous_container(_First, _End, _Old_last, _New_last);
        } else {
            const void* _Aligned_first = _Get_aligned_first(_First, _Capacity + 1);
            if (!_Aligned_first) {
                // There is no aligned address within the underlying buffer. Nothing to do
                return;
            }

            const void* _Aligned_old_last = _Old_last < _Aligned_first ? _Aligned_first : _Old_last;
            const void* _Aligned_new_last = _New_last < _Aligned_first ? _Aligned_first : _New_last;
            const void* _Aligned_end      = _End < _Aligned_first ? _Aligned_first : _End;
            __sanitizer_annotate_contiguous_container(
                _Aligned_first, _Aligned_end, _Aligned_old_last, _Aligned_new_last);
        }
    }

到了这里,关于C++ 基础: std::string的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 探索C++中std::string的弱点:你可能未曾注意到的缺点

    C++中std::string是一个非常重要的类,用于表示和处理字符串数据。它提供了一种便利的,面向对象的方式来操作字符串,大大简化了字符串操作的复杂性。 std::string在C++中的重要性: std::string提供了丰富的成员函数和操作符来处理字符串,包括连接、查找、替换、截取等功能

    2024年01月20日
    浏览(87)
  • C++之std::list<string>::iterator迭代器应用实例(一百七十九)

    简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏: Audio工程师进阶系列 【 原创干货持续更新中…… 】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:An

    2024年02月12日
    浏览(58)
  • C++ 编译错误std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >的两种解决办法

    目录 1,错误描述 2,解决办法 3,一种特殊情况 C++程序编译阶段有个常见的错误,std::__cxx11::basic_***,可能是string,list等,也许程序在其他环境完成编译,在运行环境报错,也许是正在编译阶段报错。 简单来说,这个错误的原因是因为C++不同版本对string、list的定义不同。比

    2024年02月10日
    浏览(39)
  • C/C++开发,VS2019编译报错:error C2039: “string“: 不是 “std“ 的成员

    C/C++开发,VS2019编译报错如下: 在VS2019中,对语法的检查更严格,缺少相应的头文件 添加文件件C++头文件

    2024年02月16日
    浏览(37)
  • std::find和std::string::find

    std::find 和 std::string::find 是C++标准库中常用的两个函数,用于在容器和字符串中查找特定元素或子字符串。它们的主要区别在于它们所作用的类型不同。 函数签名如下 first和last是输入的起始和结尾的迭代器,在这个范围内查找。value就是要查找的内容。 找到了就会返回指向该

    2024年02月12日
    浏览(41)
  • NSString和 std::string转换

    1、NSString转std::string 2、std::string转NSString 如果是没有中文字符,就使用: 有中文字符就使用:

    2024年02月12日
    浏览(78)
  • 【C++】string类的基础操作

    💗个人主页💗 ⭐个人专栏——C++学习⭐ 💫点击关注🤩一起学习C语言💯💫 目录 导读 1. 基本概述 2. string类对象的常见构造 3. string类对象的容量操作 4. string类对象的访问及遍历操作 5. 迭代器 6. string类对象的修改操作 6.1 基本修改操作 6.2 c_str()函数 6.3 find + npos、rfind和

    2024年03月11日
    浏览(45)
  • 解决 undefined reference to cv::imread(std::__cxx11::basic_string<char, std::char_traits<char>,....

    在使用opencv时候可能会遇到 undefined reference to cv::imread(std::__cxx11::basic_stringchar, std::char_traitschar, std::allocatorchar const, int)\\\' 其主旨原因是使用的函数版本和引用的库函数版本不一至,要确保使用的函数和引用的库函数版本一致。 1、如何知道函数版本和引用的是否一样 1.1使用nm对

    2024年02月11日
    浏览(49)
  • 【蓝桥杯备赛Java组】语言基础|竞赛常用库函数|输入输出|String的使用|常见的数学方法|大小写转换

    🎥 个人主页:深鱼~ 🔥收录专栏:蓝桥杯 🌄欢迎 👍点赞✍评论⭐收藏 目录 一、编程基础 1.1 Java类的创建  1.2 Java方法  1.3 输入输出  1.4 String的使用 二、竞赛常用库函数 1.常见的数学方法 2.大小写转换 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,

    2024年01月21日
    浏览(75)
  • C++面试八股文:用过std::set/std::map吗?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第27面: 面试官:用过 std::set/std::map 吗? 二师兄:用过。 面试官:能介绍一下二者吗? 二师兄: std::set 是一个有序的集合,其中的元素是唯一的,即每个元素只能出现一次。一般用于去重和自动排序。 二师兄: std::map 同样是

    2024年02月11日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包