在作用域中创建指针时,当指针超出作用域时,指向的变量会发生什么情况
When a pointer is created in scope, what happens to the pointed to variable when the pointer goes out of scope?
标题说明了一切。
我发现了一个本质上相同的老问题,但我需要进一步澄清。
在这个问题中,接受的答案是:
char* text = "Hello, world";
这里的自动变量(指针(是 在堆栈上创建并设置为指向常量内存中的值, 这意味着:
- " 中的字符串文本在整个程序执行过程中存在。
- 您不负责"分配"或"释放"它
- 你可能不会 改变它。如果你想改变它,那么你必须分配一些 "非常量内存"并将其复制到那里。
这是否意味着指针被删除,但指针指向的数据没有被删除?如果我在一个函数中创建 1,000,000 个指向字符的指针,当它们超出范围时,我的所有内存都会被释放吗?或者只是制作指针所需的内存,留下实际角色本身来占用我所有的记忆?
数组将在整个程序执行过程中闲逛,因为它们具有静态存储持续时间。这并不意味着您需要删除它们 - 它们应该在整个程序期间保留。事实上,调用delete
它会给你不确定的行为。您只能delete
分配了new
.
指针本身具有自动存储持续时间,并在超出范围时销毁。值得注意的是,指针必须是const char*
,因为字符串文字为您提供了一个const char
数组。考虑:
void func()
{
const char* str = "Hello";
}
包含Hello
字符数组在程序运行期间存在。指针str
仅在该函数的持续时间内存在。这里不需要deleted
任何东西。
如果你仔细想想,这很有意义。您在源代码中编写的所有这些字符串都必须存在于可执行文件中的某个位置。编译器通常将这些字符串写入可执行文件的数据段。运行程序时,可执行文件将与包含字符串的数据段一起加载到内存中。
如果程序中有两个字符串文本具有相同或重叠的文本,则编译器没有理由不能将其优化为仅存储其中一个。考虑:
void func()
{
const char* str1 = "Hello";
const char* str2 = "Hello";
const char* str3 = "lo";
}
编译器只需要在此处将Hello
字符写入可执行文件一次。前两个指针将仅指向H
,第三个指针将指向第二个l
。编译器可以进行这样的优化。当然,通过这个例子,编译器可以通过一起删除字符串来进行进一步的优化 - 它们不会以任何有助于程序可观察行为的方式使用。
所以是的,如果你有一百万个不同的字符串文字,以某种方式有助于程序的可观察行为,当然它们必须作为可执行文件的一部分存在。
我会说"什么都没有"(回答标题(,如果SO认为这是一个答案就足够了。
至于你的百万个指向字符的指针,虽然指针会被弹出(尽管你必须有相当多的堆栈来容纳百万个指针(,但它们指向的数据将困扰你的记忆。
不幸的是,您的示例不足以解决全貌。
首先,一些简单的临时词汇和解释:记忆单元是一个(输入C++(具有给定大小的内存区域,它包含一个值。多个存储单元可能包含相同的值,这无关紧要。
您应该考虑 3 种类型的存储单元:
-
"Hello, World!"
:此存储单元具有静态存储持续时间,它存在于整个程序期间 -
void foo(int a);
和void foo() { int a = 5; }
:在这两种情况下,存储单元a
都具有自动存储持续时间,一旦功能foo
返回,它就会自动消失 -
void foo() { int* a = new 5; }
:在"某处"创建一个匿名存储单元来存储值5
,并创建一个具有自动存储持续时间a
的存储单元来存储匿名存储单元的地址
那么,当指针超出范围(消失(时会发生什么?
嗯,就是这样。指针消失。最具体地说,它所指向的存储单元没有任何特殊变化。
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
事实上,在 C 和 C++ 中:
- 您可以保留不再存在的对象的地址 =>悬空引用
- 您可能会丢失现有对象的所有地址 => 内存泄漏
那么,当
char const* text = "Hello, world";
中的text
超出范围时会发生什么?
无。
指针本身占用"自动存储"(通常是堆栈(上的空间。一旦函数返回[或范围完成,但从技术上讲,几乎所有编译器都会"等待"到函数返回后再释放空间]。
如果在循环中调用同一函数 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",它调用创建text2
并指向文本"World"的bar()
,并调用创建text1
并启动Hello
的foo
。当foo
返回时,text1
内部的地址作为返回值给出,指针本身消失。printf()
完成后,bar
返回,指针消失。
只要程序正在运行,字符串"Main","Meh","Hello"和"World"仍然保持不变。
- 全局作用域中函数指针的赋值
- 错误:表达式必须具有算术、无作用域枚举或带有运算符重载的指针类型
- 如何从类函数返回指向类作用域数组的指针?
- 块作用域中的函数指针定义
- c++ 指针在离开作用域后不会停留
- 混合指向已分配对象和作用域对象的指针
- 在一个作用域中推送五个对象指针,然后检查对象的布尔值是否为 false,会给出错误
- 空的唯一指针在离开作用域时调用析构函数
- 使用作用域内生成的指针初始化静态成员
- 提升::进程间managed_shared_memory指针有效作用域
- 什么是C++中的作用域指针
- 在释放了所有作用域内指针之后仍然可访问内存
- C++指针到指针作用域的问题
- 模板类中静态函数或指针的作用域解析
- 有没有一种方法可以通过使用指针来处理作用域
- 关于 C++(或 C)中的指针的函数作用域
- 链表函数 cpp 中的指针作用域
- c++裸指针作用域
- c++对象指针作用域
- 为结构的数组创建指针作用域和构造函数