[C/C++]_[初级]_[关于把字符串string作为字节数组存储的注意点]
Posted infoworld
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C/C++]_[初级]_[关于把字符串string作为字节数组存储的注意点]相关的知识,希望对你有一定的参考价值。
场景
- 在使用
string
标准字符串的时候,有时候会把它作为动态字节数组来使用。这个string
能不能先存储字节数据,再设置它的字节数据大小?
说明
-
答案是不行,会有未定义行为。在做字节数组使用时,会使用
reverse()
方法来创建它的容量最小大小。设置完之后实际的容量大小可以通过capacity()
方法来获得。容量大小即它开闭的内存数组大小,存储数据如果超过它,那么就会有未定义行为,比如越界访问的异常。 -
string
的实际大小,通过size()
获得当前大小,它的大小必然是小于等于它的容量的。 大小只能通过以下方式改变。构造函数
: 设置它的初始大小和初始数据。append()
: 通过在末尾添加数据,并且增加对应数据大小的差值。assign()
: 覆盖原来的数据。insert()
: 指定索引位置插入数据,并增加对应数据大小的差值。erase()
: 删除指定索引区间的值,当然也会改变大小。clear()
: 清空数据,大小为0
,容量不变。resize()
: 直接创建指定大小的数据,新增加的区域默认是\\0
。void resize(size_type _Newsize, _Elem _Ch) // determine new length, padding with _Ch elements as needed if (_Newsize <= this->_Mysize) erase(_Newsize); else append(_Newsize - this->_Mysize, _Ch);
-
可见想先用存储空间再设置它的大小是容易出错的,基本都会覆盖原来的数据。
-
注意,
string
的容量会根据内部的算法进行自动扩充,除此以外就只能通过reverse
提前设置好容量。 -
string
里使用数组来存储字节数据;可以使用data()
来作为数组首地址使用;在C++17以后才会提供一个返回CharT*
数据,不需要强制转换。
string str;
str.reserve(8);
sprintf((char*)str.data(),"%d",100)
例子
- 这里举例使用
string
作为字节数组存储数据,并查看它的容量和大小的关系。
#define pKeyValue(a) cout << #a << ": " << a << endl
#define pValue(a) cout << #a << endl
#define exec(a) cout << #a << endl;a
void TestStringCapacity()
string str;
pValue(===============================);
exec(str.reserve(8192)); // 设置容量的最小大小,不一定是8192.
pKeyValue(str.capacity());
pKeyValue(str.size());
pValue(===============================);
exec(str.append("44\\0\\0\\0", 5));
pKeyValue(str.size());
pKeyValue(str.capacity());
pKeyValue(str);
pValue(===============================);
exec(str.resize(8));
pKeyValue(str.size());
pKeyValue(str);
pValue(===============================);
exec(str.resize(2));
pKeyValue(str.size());
pKeyValue(str);
pValue(===============================);
exec(auto iteSize = str.end() - str.begin());
pKeyValue(iteSize);
exec(str.clear());
pKeyValue(str.capacity());
// `string`里使用数组来存储字节数据;可以使用data()来作为数组首地址使用;
// -- 在C++17以后才会提供一个返回`CharT*`数据,不需要强制转换。
// -- 注意str里开辟的缓存大小>=8192,通过之前的reverse设置.
pValue(===============================);
exec(sprintf((char*)str.data(),"%d",100));
pKeyValue(str.size());
pKeyValue(str.c_str());
// -- 如果是存储字符串,那么只能通过strlen(str.c_str())来获取长度.
pValue(========);
pKeyValue(strlen(str.c_str()));
// -- 如果是存储字节数据,那么只能先通过resize来设置长度再进行存储数据.
pValue(========);
exec(str.resize(8));
exec(memset((void*)str.data(),'A',str.size()));
pKeyValue(str.size());
pKeyValue(str.c_str());
// -- 千万不要先存储字节再resize,因为resize会把大于原有大小的空间填充\\0,造成数据错误或丢失.
pValue(========);
exec(sprintf((char*)str.data(),"%d%d%d%d",100,100,100,100));
pKeyValue(str.c_str());
pKeyValue(str);
exec(str.resize(12));
pKeyValue(str.size());
pKeyValue(str.c_str());
输出
===============================
str.reserve(8192)
str.capacity(): 8207
str.size(): 0
===============================
str.append("44\\0\\0\\0", 5)
str.size(): 5
str.capacity(): 8207
str: 44
===============================
str.resize(8)
str.size(): 8
str: 44
===============================
str.resize(2)
str.size(): 2
str: 44
===============================
auto iteSize = str.end() - str.begin()
iteSize: 2
str.clear()
str.capacity(): 8207
===============================
sprintf((char*)str.data(),"%d",100)
str.size(): 0
str.c_str(): 100
========
strlen(str.c_str()): 3
========
str.resize(8)
memset((void*)str.data(),'A',str.size())
str.size(): 8
str.c_str(): AAAAAAAA
========
sprintf((char*)str.data(),"%d%d%d%d",100,100,100,100)
str.c_str(): 100100100100
str: 10010010
str.resize(12)
str.size(): 12
str.c_str(): 10010010
参考
以上是关于[C/C++]_[初级]_[关于把字符串string作为字节数组存储的注意点]的主要内容,如果未能解决你的问题,请参考以下文章
[C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]
[C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]
[C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]
[C/C++]_[初级]_[声明和使用字符串常量和字节常量]