C++ 类指针成员行为奇怪(错误)

c++ class pointer members acting strange(error)

本文关键字:错误 指针 成员 C++      更新时间:2023-10-16

每次调用任何函数时,公共指针成员都会被分配一个奇怪的值。 它不是调用的构造函数,因为这样值应该改变,或者至少指针地址应该改变 指针指向同一地址,但值更改 发生了什么事?

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

示例中a的指针指向构造函数后超出范围的值。指针本身保持不变,但随着调用更多函数,该值可能会被堆栈上的其他值覆盖。

每当返回对本地函数对象的引用都会导致未定义的行为,因此作为指针(在大多数情况下)。

标准 N4727- 6.6.3/7

在对象的

生命周期结束后,在对象占用的存储被重复使用或释放之前,任何引用原始对象的glvalue都可以使用,但只能以有限的方式使用。在以下情况下,程序具有未定义的行为:1.glvalue 用于访问对象 2.....

在您的示例中,它称为悬空指针。a实际上存储了一个指向堆栈地址的指针,在函数调用或堆栈展开过程中,你指向的内容总是在变化,这取决于当前的堆栈帧。

如果任何指针

指向任何变量的内存地址,但在某个变量从该内存位置删除后,指针仍然指向该内存位置。这种指针称为悬空指针,此问题称为悬空指针问题。

关于参考:

尽管引用一旦初始化,总是引用有效的对象或函数,但可以创建一个程序,其中引用对象的生存期结束,但引用仍然可访问(悬空)。访问此类引用是未定义的行为。

如果您在堆上分配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;
}