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*
是根本不同的类型。
string
和char*
之间的区别在于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::string
与 char *
作为类型无关,它是一个封装了 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 *
(如果string
是std::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*的主要内容,如果未能解决你的问题,请参考以下文章