字符串与字符* 作为类成员变量.为什么要使用字符*

string vs char* as class member variables. Why use char* at all?

本文关键字:字符 为什么 变量 字符串 成员      更新时间:2023-10-16
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::vectorstd::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 之间编组时。 但它们很少见。