📄 basic_string.h
字号:
// Components for manipulating sequences of characters -*- C++ -*-// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002// Free Software Foundation, Inc.//// This file is part of the GNU ISO C++ Library. This library is free// software; you can redistribute it and/or modify it under the// terms of the GNU General Public License as published by the// Free Software Foundation; either version 2, or (at your option)// any later version.// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// You should have received a copy of the GNU General Public License along// with this library; see the file COPYING. If not, write to the Free// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,// USA.// As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however// invalidate any other reasons why the executable file might be covered by// the GNU General Public License.//// ISO C++ 14882: 21 Strings library///** @file basic_string.h * This is an internal header file, included by other library headers. * You should not attempt to use it directly. */#ifndef _CPP_BITS_STRING_H#define _CPP_BITS_STRING_H 1#pragma GCC system_header#include <bits/atomicity.h>namespace std{ /** * @class basic_string basic_string.h <string> * @brief Managing sequences of characters and character-like objects. * * @ingroup Containers * @ingroup Sequences * * Meets the requirements of a <a href="tables.html#65">container</a>, a * <a href="tables.html#66">reversible container</a>, and a * <a href="tables.html#67">sequence</a>. Of the * <a href="tables.html#68">optional sequence requirements</a>, only * @c push_back, @c at, and array access are supported. * * @doctodo * * * @if maint * Documentation? What's that? * Nathan Myers <ncm@cantrip.org>. * * A string looks like this: * * @code * [_Rep] * _M_length * [basic_string<char_type>] _M_capacity * _M_dataplus _M_state * _M_p ----------------> unnamed array of char_type * @endcode * * Where the _M_p points to the first character in the string, and * you cast it to a pointer-to-_Rep and subtract 1 to get a * pointer to the header. * * This approach has the enormous advantage that a string object * requires only one allocation. All the ugliness is confined * within a single pair of inline functions, which each compile to * a single "add" instruction: _Rep::_M_data(), and * string::_M_rep(); and the allocation function which gets a * block of raw bytes and with room enough and constructs a _Rep * object at the front. * * The reason you want _M_data pointing to the character array and * not the _Rep is so that the debugger can see the string * contents. (Probably we should add a non-inline member to get * the _Rep for the debugger to use, so users can check the actual * string length.) * * Note that the _Rep object is a POD so that you can have a * static "empty string" _Rep object already "constructed" before * static constructors have run. The reference-count encoding is * chosen so that a 0 indicates one reference, so you never try to * destroy the empty-string _Rep object. * * All but the last paragraph is considered pretty conventional * for a C++ string implementation. * @endif */ // 21.3 Template class basic_string template<typename _CharT, typename _Traits, typename _Alloc> class basic_string { // Types: public: typedef _Traits traits_type; typedef typename _Traits::char_type value_type; typedef _Alloc allocator_type; typedef typename _Alloc::size_type size_type; typedef typename _Alloc::difference_type difference_type; typedef typename _Alloc::reference reference; typedef typename _Alloc::const_reference const_reference; typedef typename _Alloc::pointer pointer; typedef typename _Alloc::const_pointer const_pointer; typedef __gnu_cxx::__normal_iterator<pointer, basic_string> iterator; typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string> const_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; private: // _Rep: string representation // Invariants: // 1. String really contains _M_length + 1 characters; last is set // to 0 only on call to c_str(). We avoid instantiating // _CharT() where the interface does not require it. // 2. _M_capacity >= _M_length // Allocated memory is always _M_capacity + (1 * sizeof(_CharT)). // 3. _M_references has three states: // -1: leaked, one reference, no ref-copies allowed, non-const. // 0: one reference, non-const. // n>0: n + 1 references, operations require a lock, const. // 4. All fields==0 is an empty string, given the extra storage // beyond-the-end for a null terminator; thus, the shared // empty string representation needs no constructor. struct _Rep { // Types: typedef typename _Alloc::template rebind<char>::other _Raw_bytes_alloc; // (Public) Data members: // The maximum number of individual char_type elements of an // individual string is determined by _S_max_size. This is the // value that will be returned by max_size(). (Whereas npos // is the maximum number of bytes the allocator can allocate.) // If one was to divvy up the theoretical largest size string, // with a terminating character and m _CharT elements, it'd // look like this: // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT) // Solving for m: // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1 // In addition, this implementation quarters this ammount. static const size_type _S_max_size; static const _CharT _S_terminal; size_type _M_length; size_type _M_capacity; _Atomic_word _M_references; bool _M_is_leaked() const { return _M_references < 0; } bool _M_is_shared() const { return _M_references > 0; } void _M_set_leaked() { _M_references = -1; } void _M_set_sharable() { _M_references = 0; } _CharT* _M_refdata() throw() { return reinterpret_cast<_CharT*>(this + 1); } _CharT& operator[](size_t __s) throw() { return _M_refdata() [__s]; } _CharT* _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2) { return (!_M_is_leaked() && __alloc1 == __alloc2) ? _M_refcopy() : _M_clone(__alloc1); } // Create & Destroy static _Rep* _S_create(size_t, const _Alloc&); void _M_dispose(const _Alloc& __a) { if (__exchange_and_add(&_M_references, -1) <= 0) _M_destroy(__a); } // XXX MT void _M_destroy(const _Alloc&) throw(); _CharT* _M_refcopy() throw() { __atomic_add(&_M_references, 1); return _M_refdata(); } // XXX MT _CharT* _M_clone(const _Alloc&, size_type __res = 0); }; // Use empty-base optimization: http://www.cantrip.org/emptyopt.html struct _Alloc_hider : _Alloc { _Alloc_hider(_CharT* __dat, const _Alloc& __a) : _Alloc(__a), _M_p(__dat) { } _CharT* _M_p; // The actual data. }; public: // Data Members (public): // NB: This is an unsigned type, and thus represents the maximum // size that the allocator can hold. static const size_type npos = static_cast<size_type>(-1); private: // Data Members (private): mutable _Alloc_hider _M_dataplus; // The following storage is init'd to 0 by the linker, resulting // (carefully) in an empty string with one reference. static size_type _S_empty_rep_storage[(sizeof(_Rep) + sizeof(_CharT) + sizeof(size_type) - 1)/sizeof(size_type)]; _CharT* _M_data() const { return _M_dataplus._M_p; } _CharT* _M_data(_CharT* __p) { return (_M_dataplus._M_p = __p); } _Rep* _M_rep() const { return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); } // For the internal use we have functions similar to `begin'/`end' // but they do not call _M_leak. iterator _M_ibegin() const { return iterator(_M_data()); } iterator _M_iend() const { return iterator(_M_data() + this->size()); } void _M_leak() // for use in begin() & non-const op[] { if (!_M_rep()->_M_is_leaked()) _M_leak_hard(); } iterator _M_check(size_type __pos) const { if (__pos > this->size()) __throw_out_of_range("basic_string::_M_check"); return _M_ibegin() + __pos; } // NB: _M_fold doesn't check for a bad __pos1 value. iterator _M_fold(size_type __pos, size_type __off) const { bool __testoff = __off < this->size() - __pos; size_type __newoff = __testoff ? __off : this->size() - __pos; return (_M_ibegin() + __pos + __newoff); } // _S_copy_chars is a separate template to permit specialization // to optimize for the common case of pointers as iterators. template<class _Iterator> static void _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2) { for (; __k1 != __k2; ++__k1, ++__p) traits_type::assign(*__p, *__k1); // These types are off. } static void _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2) { _S_copy_chars(__p, __k1.base(), __k2.base()); } static void _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2) { _S_copy_chars(__p, __k1.base(), __k2.base()); } static void _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) { traits_type::copy(__p, __k1, __k2 - __k1); } static void _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2) { traits_type::copy(__p, __k1, __k2 - __k1); } void _M_mutate(size_type __pos, size_type __len1, size_type __len2); void _M_leak_hard(); static _Rep& _S_empty_rep() { return *reinterpret_cast<_Rep*>(&_S_empty_rep_storage); } public: // Construct/copy/destroy: // NB: We overload ctors in some cases instead of using default // arguments, per 17.4.4.4 para. 2 item 2. inline basic_string(); explicit basic_string(const _Alloc& __a); // NB: per LWG issue 42, semantics different from IS: basic_string(const basic_string& __str); basic_string(const basic_string& __str, size_type __pos, size_type __n = npos); basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Alloc& __a); basic_string(const _CharT* __s, size_type __n, const _Alloc& __a = _Alloc()); basic_string(const _CharT* __s, const _Alloc& __a = _Alloc()); basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc()); template<class _InputIterator>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -