每次调用任何函数时,公共指针成员都会被赋予一个奇怪的值。它不是被调用的构造函数,因为那时值应该被改变,或者至少指针地址应该改变 指针指向同一地址,但值会更改 发生了什么事?
class whathappened {
public:
int * a;
whathappened();
void print();
};
whathappened::whathappened() {
int b = 23;
a = &b;
}
void whathappened::print() {
cout << a << " " << *a << endl;
}
int main() {
whathappened sam;
cout << sam.a << " " << *sam.a << endl;
sam.print();
cout << sam.a << " " << *sam.a << endl;
while (1) {}
}
0133F650 23
0133F650 -858993460
0133F650 -858993460
答案 0 :(得分:5)
示例中的指针a
指向构造函数之后超出范围的值。指针本身保持不变,但是当调用更多函数时,该值很可能被堆栈上的其他值覆盖。
答案 1 :(得分:1)
任何时候返回对本地函数对象的引用都会导致未定义的行为,因此会引起指针(in most cases)。
标准N4727-6.6.3 / 7
在对象的生命周期结束之后,在重用或释放对象占用的存储之前,可以使用引用原始对象的任何glvalue,但只能以有限的方式使用....如果程序具有未定义的行为,则:1。glvalue用于访问对象2 .....
在您的示例中,它被称为dangling pointer。a
实际上存储了指向堆栈地址的指针,并且在函数调用或堆栈展开期间,您指向的内容to总是在变化,取决于当前的堆栈框架。
如果任何指针指向任何变量的内存地址但是在某个变量从该内存位置删除之后指针仍然指向这样的内存位置。这种指针被称为悬空指针,这个问题被称为悬空指针问题。
尽管引用一旦初始化,总是引用有效的对象或函数,但可以创建一个程序,其中引用对象的生命周期结束,但引用仍然可访问(悬空)。访问此类引用是未定义的行为。
答案 2 :(得分:0)
如果在堆上分配b
,那么就会出现行为,例如
whathappened::whathappened()
{
int *b = new int(23);
a = b;
}
或者,你可以做到
whathappened::whathappened()
{
a = new int(23);
}
在这种情况下,不必担心b
的范围。通过分配a = b
,我们告诉a
指出堆上的内存。这将是有效的,直到我们不在a
上调用删除。要释放a
指向的内存,您需要调用delete。像
whathappened::~whathappened()
{
delete a;
}