以下是3个功能。 main()按预期打印出来。 现在,在mycharstack()中,字符串存储在堆栈中我猜,因为“ch”超出范围,它应该不能返回字符串。它是如何正常工作的? 我想存储在mychar()中的字符串也在堆栈上。它应该正常工作吗? 我猜在代码和内存泄漏中还有其他错误,如果有的话请告诉我。我可以做这些清洁&使用std :: string更容易。但我想了解char *会发生什么。
#include <iostream>
using namespace std;
char* mychar()
{
return "Hello";
}
char* mycharstack()
{
char* ch = "Hello Stack";
return ch;
}
char* mycharheap()
{
char* ch = new char;
ch = "Hello Heap";
return ch;
}
int main()
{
cout << "mychar() = " << mychar() << endl;
cout << "mycharstack() = " << mycharstack() << endl;
cout << "mycharheap() = " << mycharheap() << endl;
system("PAUSE");
return 0;
}
答案 0 :(得分:17)
在C ++中,字符串处理不同于例如pascal。
char* mycharheap()
{
char* ch = new char;
ch = "Hello Heap";
return ch;
}
以下是:
char* ch = new char;
为一个字符创建内存,并将其分配给变量ch
ch = "Hello Heap";
分配给只读内存的变量ch
指针,其中包含字节"Hello Heap\0"
。此外,变量ch
的原始内容将丢失,从而导致内存泄漏。return ch;
返回存储到变量ch
的指针。你可能想要的是
char* mycharheap()
{
char* ch = new char[11] /* 11 = len of Hello Heap + 1 char for \0*/;
strcpy(ch, "Hello Heap");
return ch;
}
请注意strcpy
- &gt;你有ch
的内存,它有11个字符的空间,而你是从内存的只读部分用字符串填充它。
在这种情况下会有泄漏。您需要在写完后删除内存,例如:
char* tempFromHeap = mycharheap();
cout << "mycharheap() = " << tempFromHeap << endl;
delete[] tempFromHeap;
但是,我高度不建议这样做(在被叫方中分配内存并在调用方中删除)。对于这种情况,例如,有STL std::string
,另一个常见且更合理的方法是在调用者中分配,传递给被调用者,用结果“填充”内存,并再次在调用者中释放。
将导致未定义行为的原因如下:
char* mycharstack()
{
char[] ch = "Hello Heap"; /* this is a shortcut for char[11] ch; ch[0] = 'H', ch[1] = 'e', ...... */
return ch;
}
这将在堆栈上创建带有字节"Hello Heap\0"
的数组,然后尝试返回指向该数组的第一个字节的指针(可以在调用函数中指向任何内容)
答案 1 :(得分:2)
在mycharstack()中,字符串存储在堆栈中我猜,因为“ch”超出范围,它应该不能返回字符串。它是如何正常工作的?
字符串文字是指存在于静态内存中的数组。我希望你知道三个内存区域:自动内存(也称为堆栈),免费存储(又名堆)和静态内存。堆栈上的东西只是一个指针变量,你可以按值返回指针的值(它存储的地址)。所以一切都很好,除非你应该使用const char*
作为指针类型,因为你不允许修改字符串文字引用的数组。
我猜存储在mychar()中的字符串也在堆栈上。
字符串(字符数组)存储在静态存储器中。 char*
只是一种可用于传递地址的指针类型。 const
也不见了。
我猜在代码和内存泄漏中还有其他错误,如果有的话请告诉我。
泄漏是你的第三个功能。您只为堆上的一个字符分配内存,并将其地址存储到名为ch
的变量中。使用以下分配,您可以使用字符串文字的地址覆盖此地址。所以,你正在泄露记忆。
您似乎将char*
视为字符串变量的类型。但事实并非如此。它是指向字符或字符序列的指针的类型。它可能指向的指针和字符串是两个单独的东西。你应该在这里使用的是std :: string。
答案 2 :(得分:1)
您的代码中只有泄漏的char
没有错误。但这很奇怪。
char* mycharheap()
{
char* ch = new char; //creates a pointer that points to a new char in the heap
ch = "Hello Heap"; //overwrites the pointer with const char - but this cast is legal.
//note: pointer to the previous char is lost
return ch; //return the pointer to the constant area where "Hello heap" is stored.
//no, "Hello heap" is not on the heap.
}
对于“你想要什么:”部分,约塞连比我快。
答案 3 :(得分:1)
首先,如果您使用的是C ++,请使用std::string
来表示字符串。
现在回答你的问题。 char*
是指向char
(或char
s的数组)的指针。字符串文字(引号中的东西)是char
数组类型的只读对象,存储在某种只读内存中(既不在堆栈上也不在堆上)。
由于char*
是指针,因此分配指针会更改指针。所以mychar()
和mycharstack()
都返回一个指向存储在只读内存中的字符串文字的指针。
mycharheap()
只是泄密。您使用char
在堆上分配一个new char
,然后忘记其地址并返回指向字符串文字的指针。我想你的意思是:
char* mycharheap() {
char* ch = new char[strlen("Hello Heap") + 1];
strcpy(ch, "Hello Heap");
return ch;
}
然而,要重新迭代,不要在C ++中使用char*
作为字符串。使用std::string
。
答案 4 :(得分:0)
函数mycharheap()
正在泄漏:您使指针指向堆上分配的一个char
长度的内存区域,然后修改该指针以指向字符串文字,即存储在只读存储器中。分配的内存不会被释放。
答案 5 :(得分:0)
以下示例是我在尝试从函数调用中输入和输出信息时出现的问题。
#include <iostream>
#include <cstring>
using namespace std;
char* Xout(char* message);
int main()
{
const int LEN = 64;
char message[LEN], *x;
cin>>message;
x=Xout(message);
cout<<x;
return 0;
}
char* Xout(char* message)
{
int length=strlen(message);
for(int i = 0; i < length; i++)
{
message[i] = 'X';
}
return message;
}
答案 6 :(得分:0)
const char* mychar_readonly() {
// each time it returns the same pointer to char array in Read-Only memory
return "Hello Read-Only";
}
int main() {
const char* s1 = mychar_readonly();
const char* s2 = mychar_readonly();
// it will print the same addresses
// e.g s1: 0x100000f87, s2: 0x100000f87
printf("s1: %p, s2: %p\n", s1, s2);
return 0;
}