字符串与字符* 作为类成员变量.为什么要使用字符*
string vs char* as class member variables. Why use char* at all?
class Student {
public:
string name;
};
与
class Student {
public:
char* name;
};
如果我错了,请纠正我。如果我们要使用 char* 而不是字符串,我们将不得不编写我们自己的复制构造函数,因为每次我们将指针变量作为数据成员时都需要编写。右?
所以,我的问题是:为什么要使用 char*?
使用字符串,在构造函数中,我们可以直接做到:
Student(string s) {
name = s;
}
与 char* 相比,这更简单,Char* 需要:
Student(string s) {
name = new char[strlen(s)+1]; // extra 1 to store the 'n'
strcpy(name,s);
}
当用作类的数据成员时,为什么不始终使用字符串而不是 char*?
我认为char*
在C++中用作字符串的唯一原因是因为 C。我敢肯定,如果它是一种新语言,一种不努力与C兼容的语言,char*
就不会那样使用。您会注意到,将char*
处理为字符串的函数都来自 C。
请注意,在 C 中,没有字符串,因此
struct Student { char* name; };
是完全有效的 C 代码,而
struct Student { string name; };
莫。因此,在处理以前面向 C 的代码时,看到这些char*
类型并不罕见。
通常没有理由将char*
用作字符串,除非您正在编写新的字符串类、连接 C 函数或处理遗留代码。
你使用 char *
而不是 string
,因为string
是一个字符串,而char *
是指向字符对齐地址的指针。
在此基础上扩展,字符串是具有定义语义的字符向量的抽象。 在 C 语言和许多C++程序中,它表示一个分配的内存块,并保证它以 ascii NUL 字符0x00
终止。但是字符串的C++实现可以使用具有关联长度的 Pascal 字符串,或者它可以将字符串池中的字符串表示为链表。
char *
根本不提供这种保证,实际上可能不是一个字符串 - 例如,它可能是具有嵌入0x00
值的数据集合。它所承诺的只是底层架构认为是一个字符的地址。
如果需要字符串,请使用 std::string
,而不是 char*
。
一个明显的例外是与使用 char*
表示字符串的旧代码接口。不过,不要在接口层之外使用char*
。
当数据不是字符串而是原始的非结构化字节数组时,需要使用char*
。当您从文件或网络接口读取或写入二进制数据时,就是这种情况。
有时,使用 char*
而不是 string
更简单,例如,当您处理网络并且需要将充满字节的字符串转换为整数、浮点数等时。我认为使用char*
比使用string
更简单:
使用char*
char* buffer[4];
read(buffer, 4); // A random read operation
int value = *((int*)(&buffer[0]); // Not sure if it was like that...
使用string
std::string buffer;
buffer.resize(4);
read(buffer.data(), 4); // Will not work as buffer.data() returns a const char*
int value = *((int*)(&buffer.data()[0]));
string
的问题在于它旨在防止不良使用或奇怪的操作。正如有人所说,这也是因为C++是从C继承而来的。所以有一些函数(来自libc/glibc(需要char*
而不是string
。
编辑
即使char*
与char**
不同,使用std::vector
或std::string
构建二维数组也是相当复杂的,你应该制作正确的类,使用char**
,或库特定的实现(Boost,Maths libs等...
关于一个有能力的C++程序员将使用char*
的唯一地方是在extern "C"
程序的界面中,或者在非常低级的代码中,如malloc
的实现(您需要向void*
添加多个字节(。 即使调用C ABI,接口所需的char*
通常也来自&s[0]
,其中s
是一个std::string
,或者如果接口不是常量感知的(并且许多C接口不是(,那么const_cast
的结果。
char const*
更频繁一些:字符串文字毕竟是一个char const[]
,我偶尔会定义如下内容:
struct S
{
int value;
char const* name;
};
但仅适用于静态数据,例如:
S const table[] =
{
{ 1, "one" },
{ 2, "two" },
// ...
};
这可以用来避免初始化问题的顺序问题;在上面,初始化是静态的,并保证在任何动态初始化之前发生。
还有其他几种情况:我使用过char const*
,例如,在 C ABI 之间编组时。 但它们很少见。
- 为什么 Serial.println(<char[]>);返回随机字符?
- 我的字符计数代码计算错误.为什么
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 为什么签名字符可以保存大于 127 的值?
- 当我输入字符类型的数字时,为什么我无法获得整数?
- 为什么 std::string_view 比常量字符*快?
- 为什么strlen(s)与s的大小不同,为什么cout-char显示的是字符而不是数字
- 为什么我的字符* 复印机返回不同的东西?
- 为什么我可以隐式地将字符*转换为常量字符*,但不能将无符号字符*
- 为什么没有访问所有字符串字符?
- 为什么我的代码在尝试复制字符数组时引发 C6386 错误?
- 为什么C++在将浮点数转换为字符时没有显示缩小转换错误?
- 为什么char不是单个字符
- 为什么从 std::cin 读取输入后右括号字符的值有时不是")"?
- 为什么对无符号字符进行算术运算会将它们提升为有符号整数
- 为什么在 c++ 中索引字符串会发出隐式转换警告?
- 如果我们在其中输入一个整数,则字符会给出整数作为输出,但是当分配给它一个整数时,这不会发生。为什么?
- 为什么不能将字符指针定义为数组?
- 输出流中的第一个字符将替换为该流中被删除的最后一个字符.为什么会这样