C++ 指向堆栈变量的引用(&;)数据成员的行为
我遇到了一个关于使用引用数据成员的示例源代码,我对输出感到困惑。下面是示例代码C++ 指向堆栈变量的引用(&;)数据成员的行为,c++,reference,stack,scope,C++,Reference,Stack,Scope,我遇到了一个关于使用引用数据成员的示例源代码,我对输出感到困惑。下面是示例代码 class Test { private: int &t; public: Test (int y):t(y) { } int getT() { return t; } }; int main() { int x = 20; Test t1(x); cout << t1.getT() << "\n"; // Prints 20 as
class Test {
private:
int &t;
public:
Test (int y):t(y) { }
int getT() { return t; }
};
int main() {
int x = 20;
Test t1(x);
cout << t1.getT() << "\n"; // Prints 20 as output. however y has already been destroyed but still prints 20.
x = 30;
cout << t1.getT() << endl; // Prints Garbage as output Why ? Ideally both steps should be Garbage.
return 0;
}
类测试{
私人:
国际电讯,;
公众:
测试(inty):t(y){}
int getT(){return t;}
};
int main(){
int x=20;
试验t1(x);
coutx
是使用临时值通过值传递的,因此t
是对该临时值的引用,而不是x
。该临时值将在构造函数返回后被销毁。您的代码具有未定义的行为。任何内容都可以作为输出。您的问题可以通过传递对x
的引用来解决
Test (int& y):t(y);
但这不是一个好主意。在某些情况下,x
超出了范围,但仍然使用了Test
对象,那么同样的问题也会出现。x
是使用临时值传递的,因此t
是对该临时值的引用,而不是x
。该临时值将在const之后被销毁构造函数返回。您的代码有未定义的行为。任何东西都可以作为输出。您的问题可以通过传递对x
的引用来解决
Test (int& y):t(y);
但是这不是一个好主意。在某些情况下,x
超出了范围,但是仍然使用Test
对象,那么同样的问题也会出现。您的构造函数:
Test (int y):t(y) { }
将t设置为对y的引用,y是堆栈上的局部(临时)变量,而不是调用函数中的变量。更改调用函数中的变量值时,它不会更改所创建对象中的任何内容
该引用指向一个临时变量,而该临时变量在构造函数生命周期结束时丢失,这意味着getT()返回一个未定义的值
对int getT()的每次调用
访问y的内存地址。该内存地址在构造函数末尾从堆栈释放,因此它指向不在堆栈或堆上的内存,因此可以随时重用。重用时间未定义,取决于编译器和依赖库建立的其他操作。返回因此,int getT()的值取决于操作系统上影响内存的其他元素、编译器类型和版本以及操作系统等。构造函数:
Test (int y):t(y) { }
将t设置为对y的引用,y是堆栈上的局部(临时)变量,而不是调用函数中的变量。更改调用函数中的变量值时,它不会更改所创建对象中的任何内容
该引用指向一个临时变量,而该临时变量在构造函数生命周期结束时丢失,这意味着getT()返回一个未定义的值
对int getT()的每次调用
访问y的内存地址。该内存地址在构造函数末尾从堆栈释放,因此它指向不在堆栈或堆上的内存,因此可以随时重用。重用时间未定义,取决于编译器和依赖库建立的其他操作。返回int getT()的值因此,这取决于操作系统上影响内存、编译器类型和版本以及操作系统等的其他元素。现在我知道了。是的,它没有定义,但要回答我的问题,为什么在打印垃圾之前打印20或60?实际上,答案是20和60都是垃圾,理想情况下都是getT函数calls应该打印垃圾,但它不会,因为在测试t2(z)之间没有其他指令;
cout现在我明白了。是的,它是未定义的,但要回答我的问题,为什么它在打印垃圾之前打印20或60?实际上,答案是20和60都是垃圾,理想情况下,两个getT函数调用都应该打印垃圾,但它不打印。因为在测试t2(z)之间没有其他指令;
实际上,我关心的是在y的内存地址上刷新值的时间。在第一个GET语句中,它打印已经被销毁的地址的值,但仍然打印一些值而不是垃圾值。getT()
导致未定义的行为(不仅仅是“返回未定义的值”)-任何事情都有可能发生我已经添加了第三段,其中有一些关于未定义行为的细节。值得指出的是,在您的示例中,第一个getT()似乎可以工作,但它仍然没有定义-如果您运行它1000次或在另一个操作系统上运行它,您可能会得到不同的结果!实际上,我关心的是在y的内存地址上刷新值的时间。在第一个get语句中,它打印已经销毁的地址的值,但仍然打印一些值,而不是垃圾值。getT()
导致未定义的行为(而不仅仅是“返回未定义的值”)-任何事情都可能发生。我已经添加了第三段,其中包含一些有关未定义行为的详细信息。值得指出的是,在您的示例中,第一个getT()似乎可以工作,但它仍然是未定义的-如果您运行它1000次或在另一个操作系统上运行它,您可能会得到不同的结果!