C++ string类和STL

string类:

     string类由头文件string支持(头文件string.h和cstring支持对C-风格字符串进行操纵的C库字符串函数)。

  1. string的构造函数:
    string(const char* s)将string对象初始化为s指向的NBTS(C风格字符串)
    string(size_type n,char c)将string对象初始化为包含n个字符c
    string(const string & str)复制构造函数:将string对象初始化为string对象str
    string()默认构造函数:创建默认的string对象,长度为0
    string(const char* s,size_type n)将string对象初始化为s指向的NBTS的前n个字符
  2. string类的输入和C-风格字符串的输入:

string类的输入C-风格字符串的输入

string lname;

cin >> lname;     #1

getline(cin,lname);  #2

char info[10];

cin >> info;   #1

cin.getline(info,10);  #2

     string版本的getline()将自动调整目标string对象的大小,使之刚好能够存储输入的字符。

     它们的区别:读取C-风格字符串的函数getline()是istream类的方法,而string版本中getline()是独立的函数。这就是对于C- 风格字符串输入,cin是调用对象;而对于string对象输入,cin是函数参数的原因。

    3.string类的其他方法:

     string类对全部6个关系运算符都进行了重载;对每个关系运算符,都以三种方式被重载:

     operator<(const string &,const string &); operator==(const string &,const char *); operator!=(const char *,const string &).

     size()和length()成员函数都返回字符串中字符数;

     find()方法:

     当创建字符串对象时会为其分配内存块,如果字符串不断增大,超过了内存块大小,程序将分配一个大小为原来两倍的新            内存块。方法capacity()返回当前分配给字符串的内存块的大小;reserve()方法请求内存块的最小长度。

STL:

  • STL组成部分:容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分。其设计都是基于泛型编程的原则。
  • STL被组织为下面的13个头文件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack>和<utility>。
  1. 容器(containers)存储的值类型相同。头文件主要有:<vector>,<list>,<deque>,<set>,<map>,<stack>和<queue>组成。
  2. 迭代器(iterators)遍历容器的对象,与能够遍历数组的指针类似,是广义指针。头文件主要有:<utility>,<iterator>和<memory>组成。
  3. 算法(algorithms)完成特定任务(如对数组进行排序或在链表中查找特定的值)。头文件主要有:<algorithm>,<numeric>和<functional>组成。<algorithm>是所有STL头文件中最大的一个(然而它很好理解),它是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。

initializer_list:其头文件为initializer_list

  1. 这个模板类包含成员函数begin()和end()来访问列表元素、成员函数size()返回元素数。
  2. initializer_list类的初衷旨在将一系列值传递给构造函数(容器类构造函数)或其他函数(自定义函数)。
  3. initializer_list的迭代器类型为const,固不能修改initializer_list中的值;但可以将一个initializer_list赋给另一个initializer_list。 std::initializer_list<double>d = {1.1,2.2,3.3};  d = {4.4,5.5,6.6};
  4. 函数参数可以是initializer_list字面量,也可以是initializer_list变量。
    double sum(std::initializer_list<double>l1);double average(const std::initializer_list<double> &l2);

     

智能指针(auto_ptr(C++98提供的解决方案)、unique_ptr、shared_ptr、weak_ptr)

  • 智能指针是行为类似于指针的类对象,但这种对象还有其他的功能。其头文件为memory。
  • 智能指针模板使得管理由new分配的内存更容易。
  • 智能指针的思想:当程序终止时,本地变量将从栈内存中删除——因此常规指针占据的内存将被释放,但是常规指针指向的内存不会被释放。而智能指针是类对象,则可以在对象过期时,让它的析构函数删除指向的内存。

常规指针

auto_ptr

void demo1(){

   double *pd = new double; #为pd和一个double值分配存储                                                   空间,保存地址

   *pd = 25.5; #将值复制到动态内存中;

    return; #删除pd,值被保存在动态内存中

}

void demo2(){

  auto_ptr<double> ap(new double); #为ap和一个double值分配存储                                                             空间,保存地址

  *ap = 25.5;  #将值复制到动态内存中;

  return;  #删除ap,ap的析构函数释放动态内存。

}

错误示例:

auto_ptr<string> ps (new string("I reigned lonely as a cloud."));

auto_ptr<string> vocation;

vocation = ps;

若ps和vocation是常规指针,则两个指针将指向同一个string对象。这是不能接受的,因为程序将试图删除同一个对象两次——一次是ps过期时,另一次是vovation过期时。避免这种情况的方法。

定义赋值运算符,使之执行深复制。这样两个指针指向不同对象,其中一个对象是另一个对象的副本。
建立所有权概念(auto_ptr和unique_ptr)对于特定的对象,只能有一个智能指针可拥有它,这样只有拥有对象的智能指针的构造函数会删除该对象。然后,让赋值操作转让所有权。
创建智能更高的指针,跟踪引用特定对象的智能指针数这称为引用计数(shared_ptr)如:赋值时,计数将加1,而指针过期时,计数将减1.仅当最后一个指针过期时,才调用delete。
  • 在赋值操作时,auto_ptr可能在程序运行阶段崩溃;而unique_ptr则在编译器因赋值语句出现错误。

    auto_ptr<string> p1(new string("auto"));  #1

    auto_ptr<string> p2;                                 #2

    p2 = p1;                                                    #3

    unique_ptr<string> p3(new string("auto"));  #4

    unique_ptr<string> p4;                                 #5

    p4 = p3;                                                        #6

    语句3中,p2接管string对象的所有权,p1的所有权被剥夺,这可以防止p1和p2的析构函数试图删除同一个对象;但是如果程序随后试图使用p1,因p1不再指向有效数据而出错。编译器认为语句6非法,避免了p3不再指向有效数据的问题。因此,unique_ptr比auto_ptr更安全(编译阶段错误比潜在的程序崩溃更安全)。

     

 

 

 

 

  • 解决智能指针赋值后多个指针指向同一对象的问题:

using namespace std;

unique_ptr<string> pu1(new string "Hi ho!");

unique_ptr<string> pu2;

pu2 = pu1;                                                      //#1 not allowed

unique_ptr<string>pu3;

pu3 = unique_ptr<string>(new string "Yo!");   //#2 allowed

 

 

pu2 = move(pu1);         //#3

 

std::unique_ptr<double[]>p (new double(5)) //will use delete[]

  • 语句1将留下悬挂的unique_ptr(pu1),这可能导致危害;语句2不会留下悬挂的unique_ptr,因为它调用unique_ptr的构造函数,该构造函数创建的临时对象在其所有权转让给pu3后就会被销毁。固建议在容器对象中使用unique_ptr而禁止使用auto_ptr。因为如果容器算法试图对包含unique_ptr的容器执行类似于语句1的操作,将导致编译错误;如果算法试图执行类似于语句2的操作,则不会有任何问题。而对于auto_ptr,类似于语句1的操作可能导致不确定的行为和神秘的崩溃。
  • 标准库函数std::move(),将一个unique_ptr赋给另一个。
  • 相比于auto_ptr,unique_ptr还有另一个有点。它有一个可用于数组的变体。模板auto_ptr使用delete,与new一起使用;但unique_ptr有使用new[]和delete[]的版本。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值