2010-07-15 124 views
9

一个基本的问题,我不知道答案。跟踪功能是否有效?C++返回参考/堆栈内存

std::vector<int> & test_function() { 
    std::vector<int> x; 

    // do whatever 

    return x; 
} 

如果是这样,为什么?函数返回后不应该从堆栈中删除x?谢谢。

回答

11

行为未定义。您不应该返回对局部变量的引用。

+1

该死的,打我吧! – Anthony 2010-07-15 03:43:30

+1

显示的代码本身不包含任何未定义的行为。 UB会在其他调用此函数的代码中发生。 – 2010-07-15 03:52:52

8

函数是格式正确的(语法正确),但只要函数返回,返回的引用就无效并且不能使用。

澄清:有问题的代码是而不是调用任何未定义的行为。你可以安全地调用这个函数,只要你不使用返回值,例如,这是有效的:

test_function(); // ok 

但是,如果您尝试使用的返回值(即,它或副本初始化另一个参考指涉到另一个对象),那么你将调用不确定的行为,因为指涉(对象x的寿命)将已经结束(当函数返回,因为它是一个自动变量)x将被破坏:

std::vector<int>& vec = test_function(); // undefined 
std::vector<int> vec = test_function(); // undefined 
+0

值得注意的是,如果被引用的结构只是一堆POD(无指针),或者是一个基元,如果正常的堆栈框架被保留,并且您复制该值(不保留引用,那么您的第二个例如这里),原始的本地值将在返回后立即被罚款('mov esp,ebp; pop ebp;'本地栈帧不受干扰)。然而,析构函数被调用并且数据可能被操纵/改变。不过,这是一种错误的方式,并且预测会发生什么,即使在一个地方准确猜测也不是可移植的。 – 2010-07-15 03:58:12

+0

@jMerliN:即使对于POD类型的对象,结果在形式上也是未定义的。存储时间结束时,POD的寿命结束;对于局部变量,这是函数返回的点。在其生命周期结束后使用对象会导致未定义的行为。这在POD类型对象的实践中可能“工作”吗?也许,但正如你所说,这不是应该依赖的行为。 – 2010-07-15 04:01:20

+0

当多线程成为标准时,绝对不应该依赖它,因为堆栈帧的位置可能已被另一个线程重用(请注意,标准没有定义堆栈或堆的实现方式)。 – 2010-07-15 04:11:38

0

由于无法返回poi的相同原因,您无法返回对局部变量的引用因为从函数返回时,这些局部变量被解除分配,因此引用或指针变为无效。

2

是的,它是有效的,但如果你尝试使用返回的值,你会得到未定义的行为。