返回介绍

F.2 数据信息、构造函数及其他

发布于 2024-10-08 23:14:16 字数 10699 浏览 0 评论 0 收藏 0

可以根据其效果来描述构造函数。由于类的私有部分可能依赖于实现,因此可根据公用接口中可用的数据来描述这些效果。表 F.1 列出了一些方法,它们的返回值可用来描述构造函数和其他方法的效果。注意,其中的大部分术语来自 STL。

表 F.1 一些 string 数据方法

方 法

返 回 值

begin( )

指向字符串第一个字符的迭代器

cbegin( )

一个 const_iterator,指向字符串中的第一个字符(C++11)

end( )

为超尾值的迭代器

cend( )

为超尾值的 const_iterator(C++11)

rbegin( )

为超尾值的反转迭代器

crbegin( )

为超尾值的反转 const_iterator(C++11)

rend( )

指向第一个字符的反转迭代器

crend( )

指向第一个字符的反转 const_iterator(C++11)

size( )

字符串中的元素数,等于 begin( ) 到 end( ) 之间的距离

length( )

与 size( ) 相同

capacity( )

给字符串分配的元素数。这可能大于实际的字符数,capacity( ) – size( ) 的值表示在字符串末尾附加多少字符后需要分配更多的内存

max_size( )

字符串的最大长度

data( )

一个指向数组第一个元素的 const charT指针,其第一个 size( ) 元素等于this 控制的字符串中对应的元素,其下一个元素为 charT 类型的 charT(0) 字符(字符串末尾标记)。当 string 对象本身被修改后,该指针可能无效

c_str( )

一个指向数组第一个元素的 const charT指针,其第一个 size( ) 元素等于this 控制的字符串中对应的元素,其下一个元素是 charT 类型的 charT(0)字符(字符串尾标识)。当 string 对象本身被修改后,该指针可能无效

get_allocator( )

用于为字符串 object 分配内存的 allocator 对象的副本

请注意 begin( )、rend( )、data( ) 和 c_str( ) 之间的差别。它们都与字符串的第一个字符相关,但相关的方式不同。begin( ) 和 rend( ) 方法返回一个迭代器,正如第 16 章讨论的,这是一种广义指针。具体地说,begin( ) 返回一个正向迭代器模型,而 rend( ) 返回反转迭代器的一个副本。这两种方法都引用了 string 对象管理的字符串(由于 string 类使用动态内存分配,因此实际的 string 内容不一定位于对象中,因此,我们使用术语“管理”来描述对象和字符串之间的关系)。可以将返回迭代器的方法用于基于迭代器的 STL 算法中。例如,可以使用 STL reverse( ) 函数来反转字符串的内容:

而 data( ) 和 c_str( ) 方法返回常规指针。另外,返回的指针将指向存储字符串字符的数组的第一个元素。该数组可能(但不一定)是 string 对象管理的字符串的副本(string 对象采用的内部表示可以是数组,但不一定非得是数组)。由于返回的指针可能指向原始数据,而原始数据是 const,因此不能用它们来修改数据。另外,当字符串被修改后,将不能保证这些指针是有效的,这表明它们可能指向原始数据。data( ) 和 c_str( ) 的区别在于,c_str( ) 指向的数组以空值字符(或与之等价的其他字符)结束,而 data( ) 只是确保实际的字符串字符是存在的。因此,c_str( ) 方法期望接受一个 C-风格字符串参数:

同样,data( ) 和 size( ) 可用作这种函数的参数,即接受指向数组元素的指针和表示要处理的元素数目的值:

C++实现可能将 string 对象的字符串表示为动态分配的 C-风格字符串,并使用 char*指针来实现正向迭代器。在这种情况下,实现可能让 begin( )、data( ) 和 c_str( ) 都返回同样的指针,但返回指向 3 个不同的数据对象的引用也是合法的(虽然更复杂)。

在 C++11 中,模板类 basic_string 有 11 个构造函数(在 C++98 中只有 6 个)和一个析构函数:

有些新增的构造函数以不同的方式处理参数。例如,C++98 包含如下复制构造函数:

而 C++11 用三个构造函数取代了它—上述列表中的第 2~4 个,这提高了编码效率。真正新增的只有移动构造函数(使用右值引用的构造函数,这在第 18 章讨论过)以及使用 initializer_list 参数的构造函数。

注意到大多数构造函数构造函数都有一个下面这样的参数:

Allocator 是用于管理内存的 allocator 类的模板参数名;Allocator( ) 是这个类的默认构造函数。因此,在默认情况下,构造函数将使用 allocator 对象的默认版本,但它们使得能够选择使用 allocator 对象的其他版本。下面分别介绍这些构造函数。

F.2.1 默认构造函数

默认构造函数的原型如下:

通常,接受 allocator 类的默认参数,并使用该构造函数来创建空字符串:

调用该默认构造函数后,将存在下面的关系:

  • data( ) 方法返回一个非空指针,可以将该指针加上 0;
  • size( ) 方法返回 0;
  • capacity( ) 的返回值不确定。

将 data( ) 返回的值赋给指针 str 后,第一个条件意味着 str + 0 是有效的。

F.2.2 使用 C-风格字符串的构造函数

使用 C-风格字符串的构造函数让您能够将 string 对象初始化为一个 C-风格字符串;从更普遍的意义上看,它使得能够将 charT 具体化初始化为一个 charT 数组:

为确定要复制的字符数,该构造函数将 traits::length( ) 方法用于 s 指向的数组(s 不能为空指针)。例如,下面的语句使用指定的字符串来初始化 toast 对象:

char 类型的 traits::length( ) 方法将使用空值字符来确定要复制多少个字符。

该构造函数被调用后,将存在下面的关系:

  • data( ) 方法返回一个指针,该指针指向数组 s 的一个副本的第一个元素;
  • size( ) 方法返回的值等于 trains::length( ) 的值;
  • capacity( ) 方法返回一个至少等于 size( ) 的值。

F.2.3 使用部分 C-风格字符串的构造函数

使用部分 C-风格字符串的构造函数让您能够使用 C-风格字符串的一部分来初始化 string 对象;从更广泛的意义上说,该构造函数使得能够使用 charT 数组的一部分来初始化 charT 具体化:

该构造函数将 s 指向的数组中的 n 个字符复制到构造的对象中。请注意,如果 s 包含的字符数少于 n,则复制过程将不会停止。如果 n 大于 s 的长度,该构造函数将把字符串后面的内存内容解释为 charT 类型的数据。

该构造函数要求 s 不能是空值指针,同时 n<npos(npos 是一个静态类常量,它是字符串可能包含的最大元素数目)。如果 n 等于 npos,该构造函数将引发一个 out_of_range 异常(由于 n 的类型为 size_type,而 npos 是 size_type 的最大值,因此 n 不能大于 npos);否则,在该构造函数被调用后,将存在下面的关系:

  • data( ) 方法返回一个指针,该指针指向数组 s 的副本的第一个元素;
  • size( ) 方法返回 n;
  • capacity( ) 方法返回一个至少等于 size( ) 的值。

F.2.4 使用左值引用的构造函数

复制构造函数类似于下面这样:

它使用一个 string 参数初始化一个新的 string 对象:

其中,ida 将是 mel 管理的字符串副本。

下一个构造函数要求您指定一个分配器:

调用这两个构造函数中的任何一个后,将存在如下关系:

  • data( ) 方法返回一个指针,该指针指向分配的数组副本,该数组的第一个元素是 str.data( ) 指向的;
  • size( ) 方法返回 str.size() 的值;
  • capacity( ) 方法返回一个至少等于 size( ) 的值。

再下一个构造函数让您能够指定多项内容:

第二个参数(pos)指定了源字符串中的位置,将从这个位置开始进行复制:

位置编号从 0 开始,因此,位置 4 是字符 p。所以,et 被初始化为“phone home”。

第 3 个参数 n 是可选的,它指定要复制的最大字符数目,因此下面的语句将 pt 初始化为字符串“phone”:

然而,该构造函数不能跨越源字符串的结尾,例如,下面的语句将在复制句点后停止:

因此,该构造函数实际复制的字符数量等于 n 和 str.size( )-pos 中较小的一个。

该构造函数要求 pos 不大于 str.size( ),也就是说,被复制的初始位置必须位于源字符串中。如果情况并非如此,该构造函数将引发 out_of_range 异常;否则,该构造函数被调用后,copy_len 将是 n 和 str.size( )-pos 中较小的一个,并存在下面的关系:

  • data( ) 方法返回一个指向字符串的指针,该字符串包含 copy_len 个元素,这些元素是从 str 的 pos 位置开始复制而得到的;
  • size( ) 方法返回 copy_len;
  • capacity( ) 方法返回一个不小于 size( ) 的值。

F.2.5 使用右值引用的构造函数(C++11)

C++11 给 string 类添加了移动语义。正如第 18 章介绍的,这意味着添加一个移动构造函数,它使用右值引用而不是左值引用:

在实参为临时对象时将调用这个构造函数:

正如第 18 章讨论的,three 将获取 operator + () 创建的对象的所有权,而不是将该对象复制给 three,再销毁原始对象。

第二个使用右值引用的构造函数让您能够指定分配器:

调用这两个构造函数中的任何一个后,将存在如下关系:

  • data( ) 方法返回一个指针,该指针指向分配的数组副本,该数组的第一个元素是 str.data( ) 指向的;
  • size( ) 方法返回 str.size() 的值;
  • capacity( ) 方法返回一个至少等于 size( ) 的值。

F.2.6 使用一个字符的 n 个副本的构造函数

使用一个字符的 n 个副本的构造函数创建一个由 n 个 c 组成的 string 对象:

该构造函数要求 n<npos。如果 n 等于 npos,该构造函数将引发 out_of_range 异常;否则,该构造函数被调用后,将存在下面的关系:

  • data( ) 方法返回一个指向字符串第一个元素的指针,该字符串由 n 个元素组成,其中每个元素的值都为 c;
  • size( ) 方法返回 n;
  • capacity( ) 方法返回不小于 size( ) 的值。

F.2.7 使用区间的构造函数

使用区间的构造函数使用一个用迭代器定义的、STL-风格的区间:

begin 迭代器指向源字符串中要复制的第一个元素,end 指向要复制的最后一个元素的后面。

这种构造函数可用于数组、字符串或 STL 容器:

在第一种用法中,InputIterator 的类型为 const char *;在第二种用法中,InputIterator 的类型为 vector<char>::iterator。

调用该构造函数后,将存在下面的关系:

  • data( ) 方法返回一个指向字符串的第一个元素的指针,该字符串是通过复制区间[begin,end)中的元素得到的;
  • size( ) 方法返回 begin 到 end 之间的距离(度量距离时,使用的单位为对迭代器解除引用得到的数据类型的长度);
  • capacity( ) 方法返回一个不小于 size( ) 的值。

F.2.8 使用初始化列表的构造函数(C++11)

这个构造函数接受一个 initializer_list<charT>参数:

可将一个用大括号括起的字符列表作为参数:

这并非初始化 string 的最方便方式,但让 string 的接口类似于 STL 容器类。

initializer_list 类包含成员函数 begin( ) 和 end( ),调用该构造函数的影响与调用使用区间的构造函数相同:

F.2.9 内存杂记

有些方法用于处理内存,如清除内存的内容、调整字符串长度或容量。表 F.2 列出了一些与内存相关的方法。

表 F.2 一些与内存有关的方法

方 法

作 用

void resize(size_type n)

如果 n>npos,将引发 out_of_range 异常;否则,将字符串的长度改为 n,如果 n<size( ),则截短字符串,如果 n>size( ),则使用 charT(0) 中的字符填充字符串

void resize(size_type n, charT c)

如果 n>npos,将引发 out_of_range 异常;否则,将字符串长度改为 n,如果 n<size( ),则截短字符串,如果 n>size( ),则使用字符 c 填充字符串

void reserve(size_type res_arg = 0)

将 capacity( ) 设置为大于或等于 res_arg。由于这将重新分配字符串,因此以前的引用、迭代器和指针将无效

void shrink_to_fit( )

请求让 capacity( ) 的值与 size( ) 相同,这是 C++11 新增的

void clear( ) noexcept

删除字符串中所有的字符

bool empty( )const noexcept

如果 size( )==0,则返回 true

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文