简体   繁体   English

为什么以及何时必须在C ++中使用之前初始化字符串?

[英]Why and when do we have to initialize a string before using in C++?

I was reading some C++ tutorial and find that sometimes a string is initialized ('initialized' may not be the proper term), sometimes not. 我正在阅读一些C ++教程,发现有时会初始化字符串(“ initialized”可能不是正确的术语),有时却没有。

Why and when? 为什么以及何时?

The code I was reading is: 我正在阅读的代码是:

char name[50];
char lastname[50];
char fullname[100];
...
cin.getline ( name, 50 );
...
cin.getline ( lastname, 50 );
fullname[0] = '\0';            // strcat searches for '\0' to cat after
strcat ( fullname, name );     // Copy name into full name
strcat ( fullname, " " );      // We want to separate the names by a space
strcat ( fullname, lastname ); // Copy lastname onto the end of fullname

Someone please kindly explain. 请有人解释。

In C++, there are character arrays like char name[50] , and there are string classes, like std::string . 在C ++中,有字符数组,如char name[50] ,还有字符串类,如std::string

The character arrays are initialized according to the same rules are they are in C -- that is, if they are stack variables they are not initialized and if the are static / globals they are initialized to zero at load time -- there are however exceptions based on system specifics, so best is to assume that they are never initialized. 字符数组根据它们在C中的相同规则进行初始化-也就是说,如果它们是堆栈变量,则不进行初始化;如果是静态/全局变量,则在加载时将其初始化为零-但是有例外基于系统细节,因此最好是假设它们从未初始化。

string classes (like std::string) are initialized as part of the constructor phase of the object -- so they are always initialized. 字符串类(如std :: string)在对象的构造函数阶段被初始化-因此它们总是被初始化。

In your specific code, you are using character arrays of a fixed length. 在您的特定代码中,您正在使用固定长度的字符数组。 They are usually null terminated, but they may not always be -- specifically cin.getline ( name, 50 ); 它们通常以null终止,但可能并不总是-特别是cin.getline ( name, 50 ); will read full 50 characters, and it will leave the data null terminated if there are 49 characters or less in the input, but as there is no space for more than 50 characters it will not null terminate if there are 50 characters or more -- this has implications on your strcat , as strcat assumes the data is null terminated -- you must use strncat instead to make the code safe. 将读取完整的50个字符,并且如果输入的字符数少于或等于49个,则该数据将以null终止,但是由于没有空间可容纳50个以上的字符,因此如果输入的字符数为50个或更多,则不会以null终止-这会对您的strcat产生影响,因为strcat假定数据以null结尾-您必须使用strncat来确保代码安全。

Its the same like any other datatype. 与其他任何数据类型一样。 By default, local variables contain garbage values. 默认情况下,局部变量包含垃圾值。 So, you initialize it if you will be reading its value. 因此,如果要读取其值,则可以对其进行初始化。 But if you know that you will be writing to the variable, than you can skip the initialization part. 但是,如果您知道将要写入变量,则可以跳过初始化部分。

For eg: 例如:

char a[20]; //local variable

contains garbage, so you need to write some meaningful data to it before reading it. 包含垃圾,因此您需要在读取之前向其中写入一些有意义的数据。 But if you are just writing to it, then you can skip the initialization. 但是,如果您只写它,则可以跳过初始化。

What you have there is an allocation on the stack. 您所拥有的在堆栈上有一个分配。 The compiler don't guarantees that the memory allocated is empty, so you can have junk on it, that is why you need to fill with 0 to clear the junk. 编译器不保证分配的内存为空,因此您可以在其上放置垃圾,这就是为什么您需要填充0来清除垃圾的原因。

you can do that with 你可以做到

memset(pointer, '0', size);

example

char a[50]

memset(a, NULL, sizeof(char)*50);

When depends on what you are doing, if you want to write some data inside it and read, the \\0 will probably save you as it is the deadline, if you want to read all the data, char a[50] the 50 bytes ignoring the \\0, so you need to clear the data. 当取决于您的操作时,如果您想在其中写入一些数据并进行读取,则\\ 0可能会节省您的时间,因为这是截止日期;如果您想读取所有数据,则将50字节char a [50]设置为char忽略\\ 0,因此您需要清除数据。 The way to go is to clear the data inside ^^. 解决方法是清除^^内部的数据。

first_name , last_name do not get initialized immediatly because the next two lines initializet them immediatly after and full_name gets a 0 terminator so it will represent an empty string which can be concatenated upon with std::strcat. first_namelast_name不会立即初始化,因为接下来的两行会在after和full_name到0终止符后立即对其进行初始化,因此它将表示一个空字符串,可以将其与std :: strcat连接。

char first_name[50];
char last_name[50];

// There is no need to initialize first_name and last_name,
// they will contain garbage as with any uninitialized values but they get
// overwritten here when reading from stdin anyways.
cin.getline ( first_name, 50 );
cin.getline ( last_name, 50 );

char full_name[100];
// Again full_name contains garbage, so it gets a 0 terminator here in order
// to have it represent an empty string.
full_name[0] = '\0';

// full_name had to be an empty string in order to concatenate
// onto it using strcat
strcat ( full_name, first_name );
strcat ( full_name, " " );
strcat ( full_name, last_name );

That being said, these are C style strings and you would most likely prefer to just use std::string instead. 话虽这么说,这些都是C样式的字符串,您很可能更喜欢只使用std::string

cin.getline does not use or inspect the original value of the buffer you pass in, so for that function the buffer doesn't need to be initialized. cin.getline不使用或检查您传入的缓冲区的原始值,因此对于该功能,无需初始化缓冲区。

strcat , in contrast, checks the existing buffer contents to determine where it should tack on the specified string characters. 相比之下, strcat检查现有缓冲区的内容,以确定应在指定的字符串字符上附加的位置。 Therefore, with strcat the buffer must be initialized, and not just arbitrarily, but with some zero-byte that marks the logical end-of-string position. 因此,使用strcat ,不仅必须随意初始化缓冲区,而且还必须初始化一些零字节来标记逻辑字符串末尾位置。


As others have remarked, the code shown is very unsafe. 正如其他人所说,显示的代码非常不安全。 It's unsafe because (not yet remarked on as I write this) a maintenance programmer may not realize that full_name has exactly the required buffer size to hold a maximum length first name plus a space plus a maximum size last name. 这是不安全的,因为(我在撰写本文时尚未对此进行评论)维护程序员可能没有意识到full_name具有确切的缓冲区大小来容纳最大长度的名字,空格和最大大小的姓氏。 This should at the least have been explained in a comment. 至少应该在评论中对此进行了解释。

But better than a comment, safer length-checking functions should have been used. 但是比注释更好,应该使用更安全的长度检查功能。

And except for learning, even better is to use a string class such as std::string . 并且除了学习之外,更好的方法是使用诸如std::string类的字符串类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当使用 SAST 工具时,为什么我们必须为编译语言(例如 C/C++)使用“构建包装器”? - When using a SAST tool, why do we have to use a "build wrapper" for compiled languages (e.g. C/C++)? 将 int 转换为十六进制时,我们是否必须将其转换为字符串,还是可以将其保留为 int 类型? c++ - When converting an int to a hex, do we have to convert it to a string or can we keep it a type int? c++ 为什么在赋值运算符超载时必须清空当前向量? C ++ - Why do we have to empty the current vector when overloading the assignment operator? C++ 为什么我们在 C++ 中没有虚拟构造函数? - Why do we not have a virtual constructor in C++? 当我们在C ++中使用关键字“ auto”时,为什么需要多态 - Why is Polymorphism is needed when we have the keyword “auto” in C++ 什么时候我们必须在派生类c ++中定义一个析构函数 - When do we have to define a destructor in derived class c++ 当两个链接的static_cast可以完成它的工作时,为什么我们在C ++中使用reinterpret_cast? - Why do we have reinterpret_cast in C++ when two chained static_cast can do its job? 问题理解 C++ 字符串 - 为什么我们在这里使用 strcpy? - Problem understanding C++ string - why are we using strcpy here? 为什么我们在链表中设置pointer=nullpointer和pointer->next=nullpointer时会有不同的效果 - C++ - Why do we have different effect when setting pointer=nullpointer and pointer->next=nullpointer in linked list - C++ 为什么我们不能在 C++ 中初始化类的成员变量 - Why we cannot initialize the member variable of a class in C++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM