Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::string构造函数如何处理固定大小的char[]?_C++_String_C++11 - Fatal编程技术网

C++ std::string构造函数如何处理固定大小的char[]?

C++ std::string构造函数如何处理固定大小的char[]?,c++,string,c++11,C++,String,C++11,当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 在本例中,b

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

在本例中,
banz
objects字符串的大小是基于原始字符*长度还是基于复制到的字符[]?

调用的构造函数是以
const char*
作为参数的构造函数。该构造函数尝试复制该指针指向的字符数据,直到到达第一个NUL终止符。如果没有这样的NUL终止符,那么构造函数的行为是未定义的

您的
foo
类型通过指针衰减转换为
char*
,然后在调用站点发生到
const char*
的隐式转换

可能有一个模板化的
std::string
构造函数将
const char[N]
作为参数,它允许插入多个NUL字符(std::string类毕竟支持这一点),但它没有被引入,现在这样做将是一个突破性的改变;使用

std::string foo{std::begin(foo), std::end(foo)};

也将复制整个数组<代码> Foo .< /P>

首先,您必须记住(或知道)C++中的代码> char < /Cord>字符串实际上被称为<强> null终止< /强>字节串。以null结尾的位是一个特殊字符(

'\0'
),表示字符串的结尾

您必须记住(或知道)的第二件事是数组自然衰减到指向数组第一个元素的指针。对于示例中的
foo
,当您使用
foo
时,编译器确实执行
&foo[0]

最后,如果我们看一看,例如,您将看到有一个重载(数字5),它接受
常量图表*
(对于普通
字符
字符串,
图表
字符

把这一切放在一起

std::string banz(foo);
您传递一个指向
foo
的第一个字符的指针,而
std::string
构造函数将其视为以null结尾的字节字符串。通过查找空终止符,它知道字符串的长度。数组的实际大小是无关的,不使用

如果要设置
std::string
对象的大小,需要通过传递长度参数(构造函数引用中的变量4)来显式设置:

这将忽略空终止符,并将
banz
的长度设置为数组的大小。请注意,空终止符仍将存储在字符串中,因此将指针(例如由函数检索)传递给期望以空终止的字符串的函数,则该字符串将看起来很短。还请注意,null终止符之后的数据将未初始化,并且具有不确定的内容。在使用之前必须先初始化数据,否则将(甚至在C++中读取不确定数据为UB)。
正如MSalters的评论中所提到的,读取未初始化和不确定数据的UB也用于使用显式大小构造
banz
对象。它通常会工作,不会导致任何问题,但它确实打破了C++规范中规定的规则。 不过,修复它很容易:

char foo[64] = { 0 };//can hold up to 64

上述操作将把所有数组初始化为零。下面的
strcpy
调用将不会触及终止符之外的数组数据,因此数组的其余部分将被初始化。

cppreference提供了一个带有char*和int的构造函数,用于从数组中生成字符串,而不是c样式string@stefaanv还有一个
char*,int
构造函数以及这里提到的
char*
构造函数。但是没有从
模板foo(char(&str)[N])
foo(char*,size\u t)
@stefaanv的自动转换:我认为规范的C+11方式是
std::string foo{std::begin(array),std::end(array)}。可能值得强调的是,“在使用数据之前,必须先初始化该数据,
\0
”,还包括在`std::string banz(foo,sizeof foo)中使用它``@Caleth I know+在最后一次编辑答案时,我再也看不到出错的机会,评论删除我不认为阅读不确定字符不是UB;雅克·阿达涅夫劳蒙特:在你的第一句话中,你有一个双重否定。这是英文的UB。你可以使用
char-foo[64]={}太多;与C。
char foo[64] = { 0 };//can hold up to 64