当函数返回时,指向超出范围的对象的 C++ 指针 - 为啥会这样?
Posted
技术标签:
【中文标题】当函数返回时,指向超出范围的对象的 C++ 指针 - 为啥会这样?【英文标题】:C++ pointer to objects which go out of scope when function returns - why does this work?当函数返回时,指向超出范围的对象的 C++ 指针 - 为什么会这样? 【发布时间】:2013-05-16 15:31:35 【问题描述】:这两个对 get_string 和 get_string2 的调用都返回了在函数返回时超出范围的对象。返回的对象不应该是函数返回后超出范围的内存地址吗?这是使用 Visual Studio 2008。这应该总是有效吗?为什么?
#include <iostream>
enum myID SMALL, MEDIUM, LARGE ;
const char* get_string(myID id)
switch(id)
case SMALL: return "small";
case MEDIUM: return "medium";
case LARGE: return "large";
default: return "unknown";
const char* get_string2(myID id)
char* s = 0;
switch(id)
case SMALL: s = "small"; return s;
case MEDIUM: s = "medium"; return s;
case LARGE: s = "large"; return s;
default: return "unknown";
int main()
std::cout << get_string(SMALL) << std::endl;
std::cout << get_string2(SMALL) << std::endl;
return 0;
【问题讨论】:
returning a pointer to a literal (or constant) character array (string)?的可能重复 【参考方案1】:字符串文字是唯一的左值文字并且具有静态存储持续时间。所以返回一个指向字符串字面量第一个元素的指针是非常安全的。比较
const char* f1()
return "Hello"; // OK
const char* f2()
const char s[6] = "Hello";
return s; // Undefined Behavior
const char* f3()
const char* s = "Hello";
return s; //OK
从 cmets 来看,这个答案需要一些细化。好的,看,一个字符串文字存储在内存中,直到程序完成。在案例 1 中,您返回一个指向它的指针。指向的对象指针是活动的,所以没关系。在情况 3 中,您将文字的地址放入局部变量 s 并通过副本返回后者。地址的副本仍然指向有效的内存,所以没问题。然而,在第二种情况下,我们将字符串文字复制到一个本地数组 s 中,该数组在函数退出时被销毁。返回局部变量的地址是未定义的行为。
此外,如果您认为未定义的行为 实际上是未定义的,那么您也不应该感到惊讶,因为未定义的行为可能意味着
不起作用 有时有效 始终有效 做些有趣莫名的事 任何东西因此,如果某些东西有效,并不意味着它没问题。在这种情况下是这样,但不是在一般情况下。
【讨论】:
所以因为它是一个字符串文字,它不存储为堆栈变量?它存储在全局变量中吗?你有详细的网页链接吗? 您介意进一步解释一下未定义行为的情况吗?我只是想知道 只是一点点(因为效果是一样的),但是在f2
中,你不会复制任何东西(至少官方如此)。就好像你写了char const s[6] = 'H', 'e', 'l', 'l', '0', '\0' ;
。
@JamesKanze:您当然是对的,因为它是初始化,但我认为这样更容易理解。至少在这个问题上。
现在我觉得有必要再回去研究一下数组和指针的区别【参考方案2】:
此内存不会超出范围。这些是字符串文字,它们在程序运行时一直存在。
【讨论】:
以上是关于当函数返回时,指向超出范围的对象的 C++ 指针 - 为啥会这样?的主要内容,如果未能解决你的问题,请参考以下文章
当指向删除和指向不同的对象时,C++ 中的 Seg 错误指针
当指针超出范围时,由 CComObject::CreateInstance 创建的 COM 对象不会被销毁