C ++:“我的文本”是std :: string,* char还是c-string?

时间:2010-08-21 01:07:31

标签: c++ string char

我刚刚完成了a common newbie mistake

首先我们阅读one of many tutorials,如下所示:

 #include <fstream>
 int main() {
      using namespace std;
      ifstream inf("file.txt");
      // (...)
 }  

其次,我们尝试在代码中使用类似的东西,如下所示:

#include <fstream>
int main() {
    using namespace std;
    std::string file = "file.txt"; // Or get the name of the file 
                                   // from a function that returns std::string.
    ifstream inf(file);
    // (...)
}

第三,新手开发人员对一些神秘的编译器错误消息感到困惑。

问题是ifstreamconst * char 作为构造函数参数。

solutionconvert std::string to const * char

现在,真正的问题是,对于新手来说,几乎所有教程中给出的“file.txt”或类似示例看起来都像std :: string。

那么,“我的文本”是std :: string,c-string还是* char,还是取决于上下文?

您能否根据具体情况提供有关“我的文本”的解释方式的示例?

[编辑:我认为上面的例子会让它显而易见,但我应该更明确一点:我的意思是双引号中包含的任何字符串的类型,即“myfilename.txt”,而不是意思“string”这个词。]

感谢。

8 个答案:

答案 0 :(得分:10)

  

那么,“string”是std :: string,c-string还是* char,还是取决于上下文?

  • C和C ++都没有内置字符串数据类型,因此代码中的任何双引号字符串基本上都是const char *(或者说const char [])。 “C string”通常是指这个,特别是带有null终止符的字符数组。
  • 在C ++中,std::string是一个将原始字符串包装到对象中的便捷类。通过使用它,您可以避免必须自己执行(杂乱)指针算法和内存重新分配。
  • 大多数标准库函数仍然只使用char *(或const char *)个参数。
  • 您可以将char *隐式转换为std::string,因为后者有一个构造函数来执行此操作。
  • 您必须使用std::string方法将const char *明确转换为c_str()

感谢Clark Gaebel指出const ness,以及jalf和GMan提到它实际上是一个阵列。

答案 1 :(得分:7)

"myString"是字符串文字,类型为const char[9],数组为9常量char。请注意,它有足够的空间用于null终止符。因此"Hi"const char[3],依此类推。

这几乎总是正确的,没有歧义。但是,必要时,const char[9]会衰减为指向其第一个元素的const char*std::string有一个隐式构造函数,它接受const char*。因此,虽然它始终以char数组的形式开始,但如果需要它,它可以成为其他类型。

请注意,字符串文字具有const char[N]也可以衰减为char*的唯一属性,但不推荐使用此行为。如果您尝试以这种方式修改基础字符串,则最终会出现未定义的行为。这不是一个好主意。

答案 2 :(得分:3)

std::string file = "file.txt"; 

=的右侧包含一个(原始)字符串文字(即一个以空字符结尾的字节字符串)。其有效类型为array of const char

=在这里是一个棘手的小马:没有任务分配。 std::string类有一个构造函数,它将一个指向char的指针作为参数,并调用它来创建一个临时std::string,这用于复制构造(使用{{1}的副本ctor })std::string类型的对象file

编译器可以自由地删除copy ctor并直接实例化文件。

但请注意,std::string与C样式的以null结尾的字符串不同。它甚至不需要以空终止。

std:string

ifstream inf("file.txt"); 类有一个ctor,它接受std::ifstream并且传递给它的字符串文字衰减到指向字符串第一个元素的指针。

要记住的是:const char *提供(几乎无缝)C风格字符串的转换。你必须查找函数的签名,看看你是在传递std::string还是const char *(后者是因为隐式转换)。

答案 3 :(得分:2)

  

那么,“string”是std::string,c-string还是char*,还是取决于上下文?

完全取决于具体情况。 :-)欢迎使用C ++。

C字符串是以空字符结尾的字符串,几乎总是与char*相同。

根据您使用的平台和框架,“string”一词的含义可能更多(例如,它也用于引用Qt中的QStringCString中的{{1}} MFC)。

答案 4 :(得分:1)

C ++标准库提供了一个std :: string类来管理和表示字符序列。它封装了内存管理,大部分时间都是作为C字符串实现的;但这是一个实施细节。它还为常见任务提供操作例程。

std :: string类型总是那样(例如,它没有char *的转换运算符,这就是为什么你有c_str()方法),但它可以被C初始化或赋值给它-string(char *)。

另一方面,如果你有一个带std :: string或const std :: string&amp;的函数。作为参数,您可以将c-string(char *)传递给该函数,编译器将为您构建一个std :: string。根据你提出的背景,这将是一种不同的解释。

答案 5 :(得分:1)

C和C ++都没有内置的字符串数据类型。

当编译器在编译过程中发现隐式引用双引号字符串时(参见下面的代码),字符串本身存储在程序代码/文本中并生成代码以创建均匀的代码字符数组:

  • 数组是在静态存储中创建的,因为它必须保留以供稍后引用。
  • 使数组成为常量,因为它必须始终包含原始数据(Hello)。

最后,你所拥有的是这个常量静态字符数组的 const char *

const char* v()
{
    char* text = “Hello”;
    return text;
    // Above code can be reduced to:
    // return “Hello”;
}

在程序运行期间,当控件找到左括号时,它会在堆栈中创建“text”,char *指针,并在静态中创建6个元素的常量数组(包括末尾的空终结符'\ 0')记忆区。当控件找到下一行(char * text =“Hello”;)时,6元素数组的起始地址被分配给“text”。在下一行(返回文本;)中,它返回“text”。使用右括号“text”将从堆栈中消失,但是数组仍然在静态存储区中。

您不需要返回类型const。但是如果你尝试使用非常量char *更改静态数组中的值,它仍会在运行时给出错误,因为数组是常量。因此,确保返回常量总是好的,它不能被非常量指针引用。

但是如果编译器发现双引号字符串被明确地称为数组,则编译器会假定程序员将(巧妙地)处理它。请参阅以下错误示例:

const char* v()
{
    char text[] = “Hello”;
    return text;
}

在编译期间,编译器检查,引用文本并将其保存在代码中,以便在欠幅时间内填充生成的数组。此外,它计算数组大小,在这种情况下再次为6。

在程序运行期间,使用open括号,在堆栈中创建具有6个元素的数组“text []”。但没有初始化。当代码找到(char text [] =“Hello”;)时,数组被初始化(使用编译代码中的文本)。所以数组现在在堆栈上。当编译器找到(return text;)时,它返回数组“text”的起始地址。当编译器找到结束括号时,数组将从堆栈中消失。因此无法通过返回指针引用它。

大多数标准库函数仍然只使用char *(或const char *)参数。

标准C ++库有一个强大的类,称为字符串,用于处理文本。字符串的内部数据结构是字符数组。标准C ++字符串类旨在处理(并隐藏)以前C程序员所需的字符数组的所有低级操作。请注意,std :: string是一个类:

  • 您可以将char *隐式转换为std :: string,因为 后者有一个构造函数来做到这一点。
  • 您可以使用c_str()方法将std :: string显式转换为const char *。

答案 6 :(得分:0)

如果您使用的是提供此类内容的框架,则应尽可能频繁地std::string(或wxStringQString等替代方案。有时您有没有真正的选择,只能使用NUL终止的字节序列,但您通常希望尽可能避免使用它。

归根结底,根本没有明确,明确的术语。这就是生活。

答案 7 :(得分:0)

使用正确的措辞(如C ++语言标准中所示) string 是第21.3节“字符串类”中std :: basic_string(包括std :: string)的变种之一(如在C ++ 0x N3092中),而ifstream的构造函数的参数是 NTBS (以空值终止的字节序列)

引用,C ++ 0x N3092 27.9.1.4/2。

  

basic_filebuf * open(const char * s,ios_base :: openmode mode);

     

...

     如果可能,

打开一个文件,其名称为NTBS s