鉴于以下C ++代码段,行为和输出符合预期:
#include <iostream>
using namespace std;
class A {
public:
int n;
int *p;
A(int n);
};
A::A(int n) {
this->n = n;
this->p = &n;
cout << *(this->p) << endl;
}
int main(int argc, char *argv[]) {
A a(55);
cout << a.n << endl;
cout << *(a.p) << endl;
}
输出结果为:
55
55
55
但是当构造函数中的打印行被注释掉时,结果就是:
#include <iostream>
using namespace std;
class A {
public:
int n;
int *p;
A(int n);
};
A::A(int n) {
this->n = n;
this->p = &n;
// cout << *(this->p) << endl;
}
int main(int argc, char *argv[]) {
A a(55);
cout << a.n << endl;
cout << *(a.p) << endl;
}
输出:
55
32767
我意识到32767不是一个任意数字,因为它是(2 ^ 15)-1,但是为什么主方法的最终cout
语句打印的值会根据该行是否改变而改变建筑物是否已注释?
答案 0 :(得分:4)
this->p = &n;
n
这里解析为构造函数的参数。这会将p
设置为指向构造函数的参数,并将 不 设置为类成员。当构造函数终止时,p
指向一个被销毁的对象(构造函数参数值),而解除引用p
是未定义的行为。
这是反对使用构造函数参数的相同名称作为初始化的类成员名称的一个参数。很容易无意中创建未定义的行为。
将其更改为:
this->p = &this->n;
获得预期的结果。
答案 1 :(得分:4)
这一行:
this->p = &n;
表示&#34;设置this->p
以指向局部变量n
&#34;。哪个是完全正常的,除了局部变量在之后立即超出范围,之后任何取消引用p
的尝试都会调用&#34;未定义的行为&#34; (因为它指向不再正确分配的内存)。这意味着该程序可以做任何事情,包括握拳并向你猛烈晃动。 (幸运的是,目前还没有主要的编译器支持这种生物技术。)
如果您在不同的编译器上运行相同的实验,您可能会看到不同的结果,因为它非常随机。
我猜你是想要写
this->p = &(this->n);
以便它指向成员 n
?