如果需要返回 i
,下面的代码 (func1()) 是否正确?我记得在某个地方读到过当返回局部变量的引用时会有问题。那么这和 func2() 有什么不同呢?
int& func1()
{
int i;
i = 1;
return i;
}
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
如果需要返回 i
,下面的代码 (func1()) 是否正确?我记得在某个地方读到过当返回局部变量的引用时会有问题。那么这和 func2() 有什么不同呢?
int& func1()
{
int i;
i = 1;
return i;
}
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
int& func1()
{
int i;
i = 1;
return i;
}
由于你返回了一个别名(引用)指向在函数调用作用域内受限的对象,因此不会起作用。这意味着一旦func1()
返回,int i
就会被销毁,使得从函数返回的引用变得无用,因为它现在指向一个不存在的对象。
int main()
{
int& p = func1();
/* p is garbage */
}
第二个版本是有效的,因为变量是在自由存储区域分配的,而不是绑定到函数调用的生命周期上。但是,你需要负责删除所分配的 int
。
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
int main()
{
int* p = func2();
/* pointee still exists */
delete p; // get rid of it
}
通常情况下,您会将指针包装在某个RAII类和/或工厂函数中,这样您就不必自己delete
它。
无论哪种情况,您都可以只返回该值本身(尽管我意识到您提供的示例可能是虚构的):
int func3()
{
return 1;
}
int main()
{
int v = func3();
// do whatever you want with the returned value
}
请注意,像 func3()
返回原始值那样返回大型对象是完全可以的,因为现在几乎所有的编译器都实现了某种形式的返回值优化:
class big_object
{
public:
big_object(/* constructor arguments */);
~big_object();
big_object(const big_object& rhs);
big_object& operator=(const big_object& rhs);
/* public methods */
private:
/* data members */
};
big_object func4()
{
return big_object(/* constructor arguments */);
}
int main()
{
// no copy is actually made, if your compiler supports RVO
big_object o = func4();
}
有趣的是,将一个临时变量绑定到const引用在C++中是完全合法的。
int main()
{
// This works! The returned temporary will last as long as the reference exists
const big_object& o = func4();
// This does *not* work! It's not legal C++ because reference is not const.
// big_object& o = func4();
}
int* p = func2(); delete p;
现在,当您删除 'p' 时,这是否意味着在函数 func2()
的定义内分配的内存也被删除了? - Aquarius_Girlfunc2()
内分配的,并在下一行外释放的。虽然这是一种容易出错的处理内存的方式,但正如我所说,你应该使用某种RAII变体。顺便说一句,你听起来像是在学习C++。我建议你阅读一本好的入门C++书籍进行学习。此外,以后如果你有问题,可以在Stack Overflow上发布问题。评论不适合用于提问全新的问题。 - In silico局部变量是存储在栈上的内存空间,当超出范围时这块内存不会被自动失效。从更深层次的函数中(在内存中较高的位置)访问这块内存是完全安全的。
一旦函数返回并结束了,情况就变得危险起来。 通常情况下,在返回时内存不会被删除或覆盖,这意味着该地址处的内存仍然包含您的数据-指针看起来是有效的。
直到另一个函数建立起栈并将其覆盖为止。 这就是为什么这种方式能够工作一段时间的原因-但在一个特别深奥的函数集或有很多本地对象的函数之后,它突然停止工作。
甚至可能发生您再次到达同一程序部分,并使用新函数变量覆盖旧的局部函数变量。所有这些都非常危险,应该严厉禁止。
不要使用指向局部对象的指针!
int*
并返回&i
,同样是不正确的。在这种情况下,最好这样做:void func1(int& oValue)
{
oValue = 1;
}
void func1(int oValue)
{
oValue = 1;
}
不会改变oValue
的值,它只会改变函数调用中本地的oValue
的值。原因是你实际上只是在改变oValue
的“本地”副本,而不是oValue
本身。
int& i = * new int;
- Martin York