标题说明了一切。
I found an old question that is essentially the same,但我需要进一步澄清。
在这个问题中,接受的答案是:
char* text = "Hello, world";
这里是一个自动变量(指针) 在堆栈上创建并设置为指向常量内存中的值, 这意味着:
- “”中的字符串文字通过整个程序执行而存在。
- 您不负责“分配”或“释放”它
- 你可能没有 更改。如果你想改变它,那么你必须分配一些 “非恒定记忆”并将其复制到那里。
这是说删除了指针,而不是指针指向的数据吗? 如果我要在函数中创建1,000,000个指向字符的指针,当它们超出范围时我的所有内存都会被释放?或者只是制作指针所需的内存,将实际角色本身留在后面以占用我所有的记忆?
答案 0 :(得分:8)
字符数组将在程序的整个执行过程中出现,因为它们具有静态存储持续时间。这并不意味着您需要删除它们 - 它们应该在整个程序期间保持不变。实际上,在其上调用delete
会给你未定义的行为。您只能delete
使用new
分配的内容。
指针本身具有自动存储持续时间,并在超出范围时被销毁。值得注意的是,指针必须是const char*
,因为字符串文字为您提供了const char
的数组。考虑:
void func()
{
const char* str = "Hello";
}
包含Hello\0
的字符数组在程序的持续时间内存在。指针str
仅在该函数的持续时间内存在。这里不需要deleted
。
如果您考虑一下,这很有意义。您在源代码中编写的所有这些字符串都必须存在于您的可执行文件中。编译器通常将这些字符串写入可执行文件的数据段。运行程序时,可执行文件会与包含字符串的数据段一起加载到内存中。
如果程序中有两个字符串文字具有相同或重叠的文本,则编译器无法将其优化为只存储其中一个。考虑:
void func()
{
const char* str1 = "Hello";
const char* str2 = "Hello";
const char* str3 = "lo";
}
编译器只需要在此处将字符Hello\0
写入可执行文件。前两个指针只指向H
,第三个指针指向第二个l
。您的编译器可以进行这样的优化。当然,通过这个例子,编译器可以通过一起删除所有字符串来进一步优化 - 它们不会以任何有助于程序可观察行为的方式使用。
所以,是的,如果你有一百万个不同的字符串文字,它们在某种程度上促成了程序的可观察行为,当然它们必须作为你的可执行文件的一部分存在。
答案 1 :(得分:2)
我说“没有”(回答标题),如果它足以让SO认为它是一个答案。
至于你的百万字符指针,而指针会弹出(尽管你必须有一个堆栈才能容纳数百万个指针),他们指向的数据会困扰你的记忆。
答案 2 :(得分:2)
遗憾的是,你的例子不足以解决全貌。
首先,一些简单的特殊词汇和解释:内存单元是一个(在C ++中输入)具有给定大小的内存区域,它包含值 。几个存储单元可能包含相同的值,无关紧要。
您应该考虑3种类型的内存单元:
"Hello, World!"
:此内存单元具有静态存储持续时间,它在程序的整个持续时间内存在void foo(int a);
和void foo() { int a = 5; }
:在两种情况下,内存单元格a
都有自动存储持续时间,一旦函数{{1},它将自动消失返回foo
:创建一个匿名内存单元"某处"存储值void foo() { int* a = new 5; }
,并创建具有自动存储持续时间的存储单元5
以存储匿名存储的地址那么,当指针超出范围(消失)时会发生什么?
嗯,就是这样。指针消失了。最具体地说,它指向的内存单元没有什么特别的事情发生。
a
确实,在C和C ++中:
那么当
void foo(int a) { int* pointer = &a; } // pointer disappears, `a` still exists briefly void foo() { int* pointer = 0; { int a; pointer = &a; } // a disappears, pointer's value does not change... } // pointer disappears
中的text
超出范围时会发生什么?
没有
答案 3 :(得分:1)
指针本身占用“自动存储”(通常是堆栈)上的空间。一旦函数返回[或范围完成,它就会被删除,但从技术上讲,几乎所有编译器都会“等待”,直到函数在空格被释放之前返回]。
如果在循环中调用相同的函数100万次,则在任何给定时间只会有一个指针。如果你有100万个函数[和大量的内存],那么当前调用的每个函数都会有一个指针。例如。
char *foo()
{
char *text1 = "Hello";
return text1;
}
void bar()
{
char *text2 = "World!";
printf("%s %s!\n", foo(), text2);
}
void baz()
{
char *text3 = "Meh";
bar();
}
int main()
{
char *text4 = "Main";
baz();
}
当我们进入main时,在堆栈上创建了text4
- 它被初始化为字符串“Main”,它保存在其他一些内存中。当我们调用baz()
时,text3
会被创建并初始化为“Meh”,调用创建bar()
的{{1}}并指向文本“World”,并调用{ {1}}创建text2
并初始化为foo
。当text1
返回时,Hello
内的地址作为返回值给出,指针本身就会消失。当foo
完成时,text1
返回,指针消失。
只要程序正在运行,字符串“Main”,“Meh”,“Hello”和“World”仍然保留在原位。