当字符串构造函数char[]中的实际字符序列char[]可能小于最大大小时,它如何处理固定大小?
char foo[64];//can hold up to 64
char* bar = "0123456789"; //Much less than 64 chars, terminated with '\0'
strcpy(foo,bar); //Copy shorter into longer
std::string banz(foo);//Make a large string
Run Code Online (Sandbox Code Playgroud)
在这个例子中,banz对象字符串的大小是基于原始的char*length还是它被复制到的char []?
首先,您必须记住(或知道)charC++中的字符串实际上称为以空字符结尾的字节字符串.该空终止位是一个特殊字符('\0'),它告诉字符串的结尾.
你要记住(或知道)的第二件事是数组自然地衰减到指向数组第一个元素的指针.在foo您的示例中,当您使用foo编译器时确实如此&foo[0].
最后,如果我们看一下如该std::string构造函数引用,你会看到有一个接受过载(5号)const CharT*(与CharT作为一个char正常的char字符串).
把它们放在一起,用
std::string banz(foo);
Run Code Online (Sandbox Code Playgroud)
您将指针传递给第一个字符foo,std::string构造函数将其视为以空字符结尾的字节字符串.通过查找空终止符,它知道字符串的长度.数组的实际大小是无关紧要的,不使用.
如果要设置std::string对象的大小,则需要通过传递长度参数(构造函数引用中的变量4)来显式地执行此操作:
std::string banz(foo, sizeof foo);
Run Code Online (Sandbox Code Playgroud)
这将忽略null终止符并将长度设置banz为数组的大小.请注意,null-terminator仍将存储在字符串中,因此将指针(例如由c_str函数检索)传递给期望以null结尾的字符串的函数,则该字符串看起来很短.另请注意,null-terminator之后的数据将是未初始化的,并且具有不确定的内容.您必须在使用之前初始化该数据,否则您将具有未定义的行为(并且在C++中甚至读取不确定的数据是UB).
正如MSalters的评论中所提到的,读取未初始化和不确定数据的UB也用于banz使用显式大小构造对象.它通常可以工作而不会导致任何问题,但它确实违反了C++规范中规定的规则.
修复它很容易:
char foo[64] = { 0 };//can hold up to 64
Run Code Online (Sandbox Code Playgroud)
以上将所有数组初始化为零.以下strcpy调用不会触及终结符之外的数组数据,因此将初始化数组的其余部分.
| 归档时间: |
|
| 查看次数: |
240 次 |
| 最近记录: |