C++ 中string数组怎么求长度(元素个数)

在C语言中,或者说在我们平时使用的基本类型中,数组的长度都可以用 sizeof(arr)/sizeof(arr[0]) 来求得。因为sizeof运算符可以求出每个对象所占内存的字节数,并且在这些基本类型组成的数组中,每个元素所占内存空间都是相同的,因此我们可以使用 “数量 = 总价 / 单价” 这种方式来计算。

那么在C++中我们可不可以这样做呢?
请看用例:
C++ 中string数组怎么求长度(元素个数)_第1张图片
可以看到,使用这种方式我们成功求出了strArray中元素的个数。

而我们都知道的string字符串数组中每个string都是可变长度的,按理说使用 string 创建的数组每个元素所占空间大小都是不同的,那为什么仍然可以采用这种方式求成员个数呢?

string对象存储的内容大小与其所占的空间(栈空间)是没有关系的

string类型是个模板类( using string = basic_string, allocator>; ) ,其中最后一个模板参数指定类申请内存的方式。

一个简答的示例:最初str指向"aa…",数据部分地址在 str.data() 中,str对象地址为str本身。
重新填充数据后,原空间不足以容纳200个’z’将重新申请空间。
在输出的结果中,可以发现。str对象的地址没有改变,只有数据部分地址改变了。
C++ 中string数组怎么求长度(元素个数)_第2张图片

因此可以说string对象存储的内容大小与其所占的空间(栈空间)是没有关系的,因为数据部分存储在堆区中(空间适配器决定),换句话说在一个string的数组中每个string字符串所占的空间相同。
C++ 中string数组怎么求长度(元素个数)_第3张图片

参考如下示例:

string s1[] = { "1" };
string s2[] = { "1","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" };
string s3[] = { "1","2","3" };
cout << sizeof(s1) << " " << sizeof(s1[0]) << endl;
cout << sizeof(s2) << " " << sizeof(s2[0]) << " " << sizeof(s2[1]) << endl;
cout << sizeof(s3) << " " << sizeof(s3[0]) << " " << sizeof(s3[1]) << " " << sizeof(s3[2]) << endl;
// 输出
// 28 28
// 56 28 28
// 84 28 28 28

我们可以看到,s1所占总空间为 28 字节,而它只有一个成员 “1”,所占空间即为整个数组的空间。
s2所占空间为 56 字节,而它有两个元素,每个元素都占 28 字节,整个数组所占空间为 28 * 2 。
s3所占空间为 84 字节,而它有三个元素,每个元素都占 28 字节,整个数组所占空间为 28 * 3 。

如此以来,我们便可以使用 sizeof(s) / sizeof(s[0]) 来计算string数组的长度了。

string s1[] = { "1" };
string s2[] = { "1","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" };
string s3[] = { "1","2","3" };

cout << "s1 size = " << sizeof(s1) / sizeof(s1[0]) << endl;
cout << "s2 size = " << sizeof(s2) / sizeof(s2[0]) << endl;
cout << "s3 size = " << sizeof(s3) / sizeof(s3[0]) << endl;
探究 _countof 宏函数

C/C++中定义了宏函数 _countof 用于求数组元素个数。

// stdlib.h
#ifndef _countof
    #define _countof __crt_countof
#endif

// vcruntime.h
#ifdef __cplusplus
    extern "C++"
    {
        template <typename _CountofType, size_t _SizeOfArray>
        char (*__countof_helper(_UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];

        #define __crt_countof(_Array) (sizeof(*__countof_helper(_Array)) + 0)
    }
#else
    #define __crt_countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
#endif

其中在C语言中,使用的是 __crt_countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) 与我们之前讨论的方法相同。

而在C++中的代码利用了C++模板的特性。
template 这里使用了模板。_CountofType 是我们要求的数组元素的基础类型,_SizeOfArray 是数组所占内存的字节数。

我们可以类比这个宏函数的定义,写一个模板函数:

template <typename Type, size_t size>
void func(Type (&var)[size])	// 引用传参:type被解析成了元素类型,如int,而size被解析成了元素个数。这就像是使用typeid查看数组一样,
{
	cout << size << endl;
}

// 按照模板可以解析参数类型的原理,我们可以写出一个得到数组元素个数的函数。
template <typename Type, size_t size>
inline size_t getLength(const Type (&var)[size])
{
	return size;
}


C++ 中string数组怎么求长度(元素个数)_第4张图片

string [] 对象遍历

string对象自身提供了一种 s.size() 的方法(等价于length方法),用于获取字符串的长度。可以通过s[0].size()的方式获得其数组中s[0]字符串的长度。

string s[] = { "hello","world!" };
cout << s->size() << endl;		// 等价于s[0].size()
cout << s[0].size() << endl;	// 5
cout << s[1].size() << endl;	// 6

其次,如果我们想要遍历 string [] 形式数组,可以采用以下几种方式:

    string strArray[] = { "hellooooooo","happy","test","xxxx","yy" };
    
    // 法一:
    int size = _countof(strArray);
    for (int i = 0; i < size; ++i)
    {
        cout << strArray[i] << " ";
    }
    cout << "\n";

    // 法二:
    for (string& str : strArray)
    {
        cout << str << " ";
    }
    cout << "\n";

    // 法三:
    for (auto it = begin(strArray); it != end(strArray); ++it)
    {
        cout << *(it) << " ";
    }
    cout << "\n";

使用 vector 数组代替 string [] 数组

对于vector类型,这是一种数组类型,它提供了 v.size() 方法可以获取数组长度。

vector<vector<int>> v{ {1,2,3},{4,5,6,7,8},{9,10} };
cout << v.size() << endl;		// 3 
cout << v[1].size() << endl;	// 5

vector类型是一种容器适配器,其本身就是数组类型,因此类中提供了获取元素个数的方法。

而string类型同int类型,double类型一样可以作为一种基本的类型,封装到vector数组中使用。

C++ 中string数组怎么求长度(元素个数)_第5张图片

你可能感兴趣的:(日常心得,string)