C++ - char* 与 string*

Posted

技术标签:

【中文标题】C++ - char* 与 string*【英文标题】:C++ - char* vs. string* 【发布时间】:2011-06-17 02:57:41 【问题描述】:

如果我有一个指向字符串变量array of chars 的指针,那么键入是否有区别:

char *name = "name";

还有,

string name = "name";

【问题讨论】:

本例中的'string'是什么类型? string *name = "name"; 不会编译。 欺骗:***.com/questions/801209/c-char-vs-stdstring(一旦语法错误被修复)? 【参考方案1】:

是的,有区别。主要是因为你可以修改你的字符串,但你不能修改你的第一个版本——但是如果你尝试,C++ 编译器甚至不会警告你这是被禁止的。

所以总是使用第二个版本。

如果无论出于何种原因您需要使用 char 指针,请将其设为 const:

char const* str = "name";

现在,如果您尝试修改str 的内容,编译器将(正确地)禁止这样做。您还应该将编译器的警告级别提高一个档次:然后它会警告您的第一个代码(即char* str = "name")是合法的但已弃用。

【讨论】:

@康拉德鲁道夫。当你说“你的字符串变量不应该是指针”时,这是为什么呢?谢谢 @user588855:因为std::string 已经在内部管理了char * 指针,所以您只需将其用作普通对象即可。尽管如此,为避免昂贵的副本,如果您将其用作函数参数并且不需要在函数内部进行修改,请记住通过 const 引用 (const string &) 传递它。 @user588855:最简单的解释是:因为它不需要是一个。好的 C++ 代码使用尽可能少的指针,因为指针总是(总是!)导致问题。因此,现代 C++ 被设计成您几乎不需要使用指针。 @Matteo Italia。那么,string 是处理字符串的C++ 方式,而char* 是处理字符串的C 方式?那么,如果我想要一个指向 C++ 中字符串的指针,解决方案是什么?谢谢 @user588855:如果你真的想要一个指向字符串的指针,那么std::string* p = new std::string("some text");【参考方案2】:

对于初学者,你可能想要改变

string *name = "name";

阅读

string name = "name";

第一个版本无法编译,因为 string*char* 是根本不同的类型。

stringchar* 之间的区别在于char* 只是一个指向序列的指针。这种处理字符串的方法基于 C 编程语言,并且是用 C++ 对字符串进行编码的本机方式。使用 C 字符串有点棘手 - 您需要确保为它们正确分配空间,避免离开它们占用的缓冲区的末尾,将它们放在可变内存中以避免分段错误等。主要功能用于操作它们在<cstring>。大多数 C++ 程序员建议不要使用 C 风格的字符串,因为它们本质上更难使用,但它们仍然受到支持,既可以向后兼容,也可以作为低级 API 可以构建的“最低公分母”。

C++ 风格的string 是一个封装字符串的对象。用户看不到其内存管理的详细信息(尽管可以保证所有内存都是连续的)。它使用运算符重载使一些常见的操作(如连接)更易于使用,并且还支持几个旨在执行高级操作(如搜索、替换、子字符串等)的成员函数。它们还旨在与 STL 算法互操作,尽管 C -style 字符串也可以做到这一点。

简而言之,作为 C++ 程序员,您最好使用 string 类型。它更安全,更易于使用。了解 C 风格的字符串仍然很好,因为您肯定会在您的编程生涯中遇到它们,但最好不要在您的程序中使用它们,因为 string 也可以使用,除非有令人信服的理由这样做。

【讨论】:

这种情况我可能没有得到,因为我指向一个 string 变量,指针不应该是 same 类型的变量吗?是指着什么?那是string*?谢谢 @user588855- 与 C 风格的字符串不同,C++ 字符串不是指针。它们是具有自己的字符串副本的具体对象。字符串类型的设计使您可以使用 C 样式字符串初始化 C++ 字符串,因此您将希望在声明中使用字符串,而不是指向字符串的指针。诚然,这有点奇怪,但是如果您将其视为“我正在制作一个与此 C 样式字符串相等的新字符串”而不是“我正在指向一个旧字符串”,那么您会得到正确的想法。【参考方案3】:

是的,第二个不是有效的 C++! (它不会编译)。

您可以通过多种方式创建string,但其中一种方式如下:

string name = "name";

请注意,不需要*,因为我们不需要将其声明为指针。

【讨论】:

那么,如果我有一个string 类型的变量,那么pointer 这个变量的唯一类型是char*?谢谢 @user588855:不。 std::stringchar * 作为类型无关,它是一个封装了 C 字符串的 class,提供复制语义、自动调整大小和许多其他有用的东西。这里的关键是 string 对象可以用 C 字符串文字初始化(因为它有一个以 const char * 作为参数的构造函数),然后将其复制到其内部它自己管理的缓冲区。【参考方案4】:

char* name = "name" 应该是无效的,但可以在大多数系统上编译,以便向后兼容没有 const 的旧时代,并且如果不编译它会破坏大量遗留代码。但它通常会收到警告。

危险在于你得到一个指向可写数据的指针(根据 C++ 规则可写),但如果你真的尝试写入它,你会调用 Undefined Behaviour,并且语言规则应该尽量保护你免受这种情况的影响尽可能合理。

正确的结构是

const char * name = "name";

上面没有错,即使在 C++ 中也是如此。使用字符串并不总是更正确。

你的第二个陈述应该是

std::string name = "name";

string 是标准库中定义的类(实际上是basic_string<char,char_traits<char>,allocator<char> 的 typedef),因此在命名空间 std 中(basic_string、char_traits 和分配器也是如此)

在各种情况下,使用字符串比使用 char 数组更可取。例如,在您的直接情况下,您可以修改它。所以

name[0] = 'N';

(将第一个字母转换为大写)对字符串有效,对 char*(未定义行为)或 const char *(不会编译)无效。如果你有char name[] = "name";

,你将被允许修改字符串

但是,如果想要将一个字符附加到字符串,std::string 构造是唯一可以让您干净地执行此操作的构造。使用旧的 C API,您必须使用 strcat(),但除非您分配了足够的内存来执行此操作,否则这将无效。

std::string 为您管理内存,因此您不必调用 malloc() 等。实际上分配器,第三个模板参数,管理下面的内存 - basic_string 请求它需要多少内存,但被解耦来自实际使用的内存分配技术,因此即使使用 std::string,您也可以使用内存池等来提高效率。

此外,basic_string 实际上并不执行许多字符串操作,而是通过 char_traits 完成的。 (这允许它使用经过优化的专业 C 函数)。

因此,当您处理在运行时构造和传递的动态字符串(而不仅仅是文字)时,

std::string 是管理字符串的最佳方式。

您很少会使用字符串*(指向字符串的指针)。如果你这样做,它将是一个指向对象的指针,就像任何其他指针一样。您将无法按照您的方式分配它。

【讨论】:

【参考方案5】:

C++ 字符串类是对 char 类 C 字符串的封装。它更方便(http://www.cplusplus.com/reference/string/string/)。

对于旧版,您始终可以从字符串变量中“提取”字符指针以将其作为字符指针处理:

    char * cstr;
    string str ("Please split this phrase into tokens");
    cstr = new char [str.size()+1];
    strcpy (cstr, str.c_str());    //here str.c_str() generate null terminated char* pointer
    //str.data() is equivalent, but without null on end

【讨论】:

【参考方案6】:

是的,char* 是指向字符数组的指针,它是一个字符串。 string * 是指向std::string 数组的指针(很少使用)。

string *name = "name"; 

“name”是一个const char*,它永远不会被转换成一个std::string*。这将导致编译错误。

有效的声明:

string name = "name";

const char* name = "name"; // char* name = "name" is valid, but deprecated

【讨论】:

不。 string *(如果stringstd::string)是一个指向std::string 类实例的指针,这是非常罕见的事情,因为您几乎总是处理std::string 实例,而不是指向它们的指针(并且您不会使用字符串文字初始化 string *)。 @Matteo:我知道这些事情,但也许我的解释很糟糕。谢谢指正。 @Hoàng Long:现在或多或少都可以(删除了反对票),我不知道是我读错了还是被忍者编辑了。不过,您应该更清楚地说明“字符串”不同于 string(别名 std::string @Hoàng Long:只需将最后一行更改为const char *,您就会得到我的支持。 :)char * 用于字符串文字是合法的,但已弃用) @Matteo:为您的评论+1,而不是为赞成票,而是因为从 const char* 到 char* 的转换确实已被弃用。我以前在大学里做过很多。谢谢【参考方案7】:
string *name = "name";

在 GCC 中不编译。

【讨论】:

以上是关于C++ - char* 与 string*的主要内容,如果未能解决你的问题,请参考以下文章

C++中string和char字符串的异同与使用方法

在 C++ 中将字符串转换为 Cstring

C++里把char转化为string怎么解决

C++中如何将int或者char转化为string类

如何在 C++ 中删除 char* [重复]

用自身初始化一个字符串(C++)