从函数返回对局部变量的 const 引用
-
13-09-2019 - |
题
我对从函数返回对局部变量的引用有一些疑问:
class A {
public:
A(int xx)
: x(xx)
{
printf("A::A()\n");
}
};
const A& getA1()
{
A a(5);
return a;
}
A& getA2()
{
A a(5);
return a;
}
A getA3()
{
A a(5);
return a;
}
int main()
{
const A& newA1 = getA1(); //1
A& newA2 = getA2(); //2
A& newA3 = getA3(); //3
}
我的问题是 =>
是否实施
getA1()
正确的?我觉得它不正确,因为它返回局部变量或临时变量的地址。中的哪一条语句
main
(1,2,3)会导致未定义的行为吗?在
const A& newA1 = getA1();
该标准是否保证 const 引用的临时绑定在引用超出范围之前不会被销毁?
解决方案
1.是
getA1()
实施正确吗?我觉得它不正确,因为它返回局部变量或临时变量的地址。
唯一的版本是 getAx()
你的程序中正确的是 getA3()
. 。无论您以后如何使用它们,其他两个都有未定义的行为。
2.main(1,2,3) 中的哪些语句会导致未定义的行为?
从某种意义上说,他们都不是。对于 1 和 2,未定义的行为是函数体的结果。对于最后一行, newA3
应该是一个编译错误,因为您无法将临时值绑定到非常量引用。
3.在
const A& newA1 = getA1();
标准是否保证暂时受const
在引用超出范围之前引用不会被销毁?
不。下面是一个例子:
A const & newConstA3 = getA3 ();
这里, getA3()
返回一个临时对象,并且该临时对象的生命周期现在绑定到该对象 newConstA3
. 。换句话说,临时的将存在直到 newConstA3
超出范围。
其他提示
问题一:是的,这是一个问题,请参阅问题 2 的答案。
问题2:1 和 2 未定义,因为它们引用 getA1 和 getA2 堆栈上的局部变量。这些变量超出了范围,不再可用,更糟糕的是,随着堆栈不断变化,这些变量可能会被覆盖。getA3 可以工作,因为创建了返回值的副本并将其返回给调用者。
Q3:不存在这样的保证来看到问题 2 的答案。
我认为主要问题是你根本没有返回临时工,你应该
return A(5);
而不是
A a(5);
return a;
否则,您将返回局部变量地址,而不是临时变量地址。而临时到 const 的引用仅适用于临时变量。
我认为它的解释在这里:临时到 const 引用
如果你在 VC6 上编译它,你会收到这个警告
******编译器警告(1级)C4172返回本地变量或临时函数的函数返回本地变量或临时对象的地址。函数返回时局部变量和临时对象都会被销毁,因此返回的地址无效。*****
在测试这个问题时,我发现了有趣的事情(给定的代码在 VC6 中工作):
class MyClass
{
public:
MyClass()
{
objID=++cntr;
}
MyClass& myFunc()
{
MyClass obj;
return obj;
}
int objID;
static int cntr;
};
int MyClass::cntr;
main()
{
MyClass tseadf;
cout<<(tseadf.myFunc()).objID<<endl;
}