我在教自己C++,我对指针有点困惑(特别是在下面的源代码中).但首先,我继续向你展示我所知道的内容(然后将代码与此对比,因为我觉得好像存在一些矛盾).
我知道的:
int Age = 30;
int* pointer = &Age;
cout << "The location of variable Age is: " << pointer << endl;
cout << "The value stored in this location is: " << *pointer << endl;
Run Code Online (Sandbox Code Playgroud)
指针保存内存地址.使用间接(取消引用)运算符(*),可以访问存储在指针的内存位置的内容.在本书的代码中,我无法理解......
cout << "Enter your name: ";
string name;
getline(cin, name); //gets full line up to NULL terminating character
int CharsToAllocate = name.length() + 1; //calculates length of string input
//adds one onto it to adjust for NULL character
char* CopyOfName = new char[CharsToAllocate];
// pointer to char's called CopyOfName, is given the memory address of the
//beginning of a block
//of memory enough to fit CharsToAllocate. Why we added 1? Because char's need a
//NULL terminating character (\0)
strcpy(CopyOfName, name.c_str()); //copies the string name, into a pointer?
cout << "Dynamically allocated buffer contains: " << CopyOfName << endl;
delete[] CopyOfName; //always delete a pointer assigned by new to prevent memory leaks
Run Code Online (Sandbox Code Playgroud)
输出:
Enter your name: Adam
Dynamically allocated buffer contains: Adam
Run Code Online (Sandbox Code Playgroud)
上面代码中的注释是我的评论.我的问题始于strcpy.为什么要name.c_str()复制到指针CopyOfName?这是否意味着所有字符串都是必不可少的指针?就像字符串测试="Hello world"; 实际上是指向存储"H"的存储位置的指针吗?
接下来,为什么它在print out语句中使用CopyOfName而不是*CopyOfName?指针有内存地址吗?使用*CopyOfName会打印出内存位置的内容.我在Code :: Blocks中尝试了这个,如果输入文本是"Hello World".*CopyOfName在打印输出语句中使用只会给出"H".这是有道理的,因为当我声明我需要一个带有'new'的内存块时,这实际上会返回一个指向动态分配的内存块的第一部分的指针.
我可以调和它的唯一方法是字符串实际上是一个指针.
string testing = "Confused";
cout << testing << endl;
Run Code Online (Sandbox Code Playgroud)
会打印出"困惑"这个词
但是,如果我尝试编译
string testing = "Confused";
cout << *testing;
Run Code Online (Sandbox Code Playgroud)
我收到一条错误消息.
基本上,总结一下我的问题,我试图理解代码strcpy和cout声明.
And*_*nko 17
看起来你理解C风格的字符串是什么,但总而言之,它们只是内存中的字符数组,按照惯例以nul字符终止\0.通常它们通过char*指向字符串中的第一个字母来引用.当它们被打印时,通常从第一个字符开始打印字符串的字符,并且当到达\0终止符时打印(或复制等)停止.
An std::string是一个(通常)包装C风格字符串的类.这意味着std::string对象(通常)具有用于实现其功能的私有C样式字符串.该函数std::string::c_str()返回指向此底层C样式字符串的指针.
我们假设它char *str;指向C风格的字符串.如果您尝试运行cout << *str << endl;,您会注意到只打印了第一个字符.那是因为C++的函数重载.数据类型*str是char,所以调用char版本cout并忠实地打印单个字符*str.对于C风格的字符串兼容的版本cout,需要一个char*作为参数对待指针作为C风格的字符串印刷目的.例如,如果您cout是int*,int则不会打印基础.
编辑:另一个评论:
您尝试取消引用std::string对象失败的原因是,它确实不是指针.您可以取消引用的返回值std::string::c_str(),然后您将返回第一个char字符串.
在 C 中,字符串只是字符数组。当用作函数的参数时,数组会衰减为指针。
在 C++ 中,std::string是一个类。它在其中包含一个 C 风格的字符数组,这就是c_str()返回的内容。但是字符串本身不是指针,所以你不能解引用它;您必须使用该c_str()方法来获取指向字符串内容的指针。
小智 5
指针与数组不同。字符串文字是不可变的,当您有一个指向字符串文字的指针时,您可以检查其内容,但修改它们是未定义的行为。使用此语法时:
char arr[] = "hi there";
Run Code Online (Sandbox Code Playgroud)
字符串文字被复制到数组中。由于您没有指定大小,编译器会自动推导它。终止符NUL也会自动添加。如果指定大小,则必须确保缓冲区可以容纳NUL终止符。所以:
char arr[5] = "hello";
Run Code Online (Sandbox Code Playgroud)
是一个错误。如果您使用大括号初始值设定项语法:
char arr[5] = { "h", "e", "l", "l", "o" };
Run Code Online (Sandbox Code Playgroud)
这是一个错误,因为没有NUL终止符。如果您使用strcpy,NUL将为您添加一个终止符。
std::string提供了两种返回指向其底层内容的指针的方法:data和c_str。C++11 之前的版本,唯一的区别是data不包含NUL终止符。在 C++11 中,现在是这样,因此它们的行为是相同的。因为指针很容易失效,所以操作这些指针是不安全的。这样做也不安全char * ptr = str.c_str();,因为返回的数组的生命周期c_str在分号处消失。您需要将其复制到缓冲区中。