标准库string类型及其实现原理

1 string简介

string类型支持长度可变的字符串,C++标准库将负责管理与存储字符串相关的内存,以及提供各种有用的操作。

2 string头文件

#include<string>
#using std:string;

3 string 操作

3.1 string初始化

sting s1;		//默认构造函数
string s2(s1);		//将s2初始化为s1的副本
string s3("value");	//将s3初始化为字符串“value”的副本
string s4(n,'c');	//将s4初始化为字符'c'的n个副本

3.2 获取string对象中字符的个数——string::size()

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s1("Hello World!");
	cout<<"count:"<<s1.size()<<endl;
}

输出:

[root@localhost tmp]# ./string
count:12
这里需要注意的是, string::size()操作返回的类型是string::size_type,不是int类型,也绝对不允许将返回值赋值给int类型

3.3 判断string对象是否为空——string::empty()

返回bool类型

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s1("Hello World!");
	string s2;
	cout<<"s1 is empty?:"<<(s1.empty()?"True":"False")<<endl;
	cout<<"s2 is empty?:"<<(s2.empty()?"True":"False")<<endl;
}

输出:

[root@localhost tmp]# ./string
s1 is empty?:False
s2 is empty?:True

3.4 string的关系操作符(==,!=,<,<=,>,>=)

1) 两个string对象相等是指他们的长度相同,且含有排序相同的字符。

2) 如果两个string对象长度不同,且短的string对象与长的string对象的前面部分相匹配,则短的string对象小于长的string对象

3) 如果两个string对象的字符不同,则比较第一个不匹配的字符。

3.5 string 对象赋值

赋值操作之后,s4包含了s2字符串的一个副本

#include<iostream>
#include<string>
using namespace std;
int main()
{
	cout << s3 << endl;
	cout << s4 << endl;
}

输出:

Hello World!
Hello World!
[root@localhost tmp]# 

3.6 string对象的连接及与字符串字面值的连接

字符串字面值不能单独用+操作进行连接操作

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s3 = "Hello World!";
	string s4 = "My God!";
	string s5 = s3+s4;
	string s6 = s3 + "My God!";
	//string s7 = "Hello World!" + "My God!"; error
	cout << s5 << endl;
	cout << s6 << endl;
}

输出:

Hello World!My God!
Hello World!My God!
[root@localhost tmp]# 
string.cpp:15:31: error: invalid operands of types ‘const char [13]’ and ‘const char [8]’ to binary ‘operator+’
  string s7 = "Hello World!" + "My God!"; 

3.7 string下标操作([])

string类型通过下标操作符([])来访问string对象中的单个字符。下标操作符需要取一个string::size_type类型的值,来标明要访问字符的位置。

#include<iostream>
#include<string>
using namespace std;
int main()
{

	string s3 = "Hello World!";
	for(string::size_type i=0;i!=s3.size();i++)
	{
		cout<<s3[i]<<endl;
	}

	s3[0]='*'; //操作左值

	cout << s3 << endl;

}

输出

H
e
l
l
o
 
W
o
r
l
d
!
*ello World!
[root@localhost tmp]# 

4 string的实现

4.1 string的实现

其实string是basic_string模板类的一种实现.在stl_string_fwd.h文件中可以看得出:

#ifndef __SGI_STL_STRING_FWD_H
#define __SGI_STL_STRING_FWD_H

#include <stddef.h>
#include <stl_config.h>
#include <stl_alloc.h>
#include <char_traits.h>

__STL_BEGIN_NAMESPACE

template <class _CharT, 
          class _Traits = char_traits<_CharT>, 
          class _Alloc = __STL_DEFAULT_ALLOCATOR(_CharT) >
class basic_string;

typedef basic_string<char>    string;
typedef basic_string<wchar_t> wstring;

static const char* __get_c_string(const string&);

__STL_END_NAMESPACE

#endif /* __SGI_STL_STRING_FWD_H */

// Local Variables:
// mode:C++

4.2 string的底层存储实现(非__STL_USE_STD_ALLOCATORS)

basic_string继承了_String_base

template <class _CharT, class _Traits, class _Alloc> 
class basic_string : private _String_base<_CharT,_Alloc> {
public:
  typedef _CharT value_type;
  typedef _Traits traits_type;

  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type& reference;
  typedef const value_type& const_reference;

看下_String_base

template <class _Tp, class _Alloc> class _String_base {
public:
  typedef _Alloc allocator_type;
  allocator_type get_allocator() const { return allocator_type(); }

protected:
  typedef simple_alloc<_Tp, _Alloc> _Alloc_type;

  _Tp* _M_start;
  _Tp* _M_finish;
  _Tp* _M_end_of_storage;
                                // Precondition: 0 < __n <= max_size().

  _Tp* _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); }
  void _M_deallocate(_Tp* __p, size_t __n) {
    if (__p)
      _Alloc_type::deallocate(__p, __n); 
  }

  void _M_allocate_block(size_t __n) { 
    if (__n <= max_size()) {
      _M_start  = _M_allocate(__n);
      _M_finish = _M_start;
      _M_end_of_storage = _M_start + __n;
    }
    else
      _M_throw_length_error();
  }

  void _M_deallocate_block() 
    { _M_deallocate(_M_start, _M_end_of_storage - _M_start); }
  
  size_t max_size() const { return (size_t(-1) / sizeof(_Tp)) - 1; }

  _String_base(const allocator_type&)
    : _M_start(0), _M_finish(0), _M_end_of_storage(0) { }
  
  _String_base(const allocator_type&, size_t __n)
    : _M_start(0), _M_finish(0), _M_end_of_storage(0)
    { _M_allocate_block(__n); }

  ~_String_base() { _M_deallocate_block(); }

  void _M_throw_length_error() const;
  void _M_throw_out_of_range() const;
};

留意到_String_base的非空构造函数调用_M_allocate_block分配内存空间,本质上是调用STl的内存分配器实现的:

  _Tp* _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); }
所以本质上,string是一片STL管理的堆内存(STL内存池或直接malloc分配的)








猜你喜欢

转载自blog.csdn.net/idwtwt/article/details/80574437