当前位置:嗨网首页>书籍在线阅读

02-数据信息、构造函数及其他

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

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

可以根据其效果来描述构造函数。由于类的私有部分可能依赖于实现,因此可根据公用接口中可用的数据来描述这些效果。表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()函数来反转字符串的内容:

string word;
cin >> word;
reverse(word.begin(), word.end());

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

string file("tofu.man");
ofstream outFile(file.c_str());

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

string vampire("Do not stake me, oh my darling!");
int vlad = byte_check(vampire.data(), vampire.size());

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

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

explicit basic_string(const Allocator& a = Allocator());
basic_string(const charT* s, const Allocator& a = Allocator());
basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
basic_string(const basic_string& str);
basic_string(const basic_string& str, const Allocator&);
basic_string(const basic_string& str, size_type pos,
    size_type n = npos, const Allocator& a = Allocator());
basic_string(basic_string&& str) noexcept;
basic_string(const basic_string&& str, const Allocator&);
basic_string(size_type n, charT c, const Allocator& a = Allocator());
template<class InputIterator>
basic_string(InputIterator begin, InputIterator end,
    const Allocator& a = Allocator());
basic_string(initializer_list<charT>, const Allocator& = Allocator());
~basic_string();

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

basic_string(const basic_string& str, size_type pos = 0,
    size_type n = npos, const Allocator& a = Allocator());

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

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

const Allocator& a = Allocator()

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