C++ C++;返回对局部变量的引用
如果必须返回i,则以下代码(func1())是否正确?我记得在某个地方读到过,当返回对局部变量的引用时出现问题。它与func2()有何不同 此代码段:C++ C++;返回对局部变量的引用,c++,C++,如果必须返回i,则以下代码(func1())是否正确?我记得在某个地方读到过,当返回对局部变量的引用时出现问题。它与func2()有何不同 此代码段: int& func1() { int i; i = 1; return i; } 将不起作用,因为您返回的对象的别名(引用)的生存期限制在函数调用的范围内。这意味着一旦func1()返回,int i就会消失,使得从函数返回的引用变得毫无价值,因为它现在引用的是一个不存在的对象 int main() { i
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
}
通常,您会将指针封装在某个类和/或工厂函数中,这样您就不必自己删除它
无论哪种情况,您都可以返回值本身(尽管我知道您提供的示例可能是人为的):
请注意,以与func3()
返回基元值相同的方式返回大对象是完全正确的,因为现在几乎每个编译器都实现了某种形式的:
有趣的是,将临时变量绑定到常量引用是非常困难的
局部变量是堆栈上的内存,当超出范围时,该内存不会自动失效。从嵌套更深的函数(内存中堆栈的更高位置)访问此内存是完全安全的 一旦函数返回并结束,事情就会变得危险。 通常,当您返回时,内存不会被删除或覆盖,这意味着该地址的内存仍然包含您的数据-指针似乎有效 直到另一个函数建立堆栈并覆盖它。 这就是为什么它可以工作一段时间,然后在一组嵌套特别深的函数,或者一个具有非常大的大小或许多本地对象的函数再次到达堆栈内存后突然停止工作 您甚至可能再次访问相同的程序部分,并用新的函数变量覆盖旧的局部函数变量。所有这些都是非常危险的,应该予以大力劝阻。
不要使用指向本地对象的指针要记住的一件事是这些简单的规则,它们适用于参数和返回类型
- 值-制作相关项目的副本李>
- 指针-指相关项目的地址
- 参考-是字面上有问题的项目
int*
和返回&i
同样是不正确的。如果那样的话,你最好这样做
void func1(int& oValue)
{
oValue = 1;
}
这样做将直接更改传入参数的值。鉴于此代码
void func1(int oValue)
{
oValue = 1;
}
不会。它只需将
oValue
local的值更改为函数调用。这是因为您实际上只是更改了oValue
的一个“本地”副本,而不是oValue
本身。如果将func1()更改为使用动态分配的内存,则它们是相同的:-)int&i=*new int代码>与const locals相关:漂亮的解释:hattip:在第三个代码段中,您正在删除int*p=func2();删除p
现在,当您删除“p”时,是否意味着在函数func2()
的定义“内部”分配的内存也被删除了?@Anisha Kaul:是的。内存在func2()
内部分配,并在下一行的外部释放。不过,这是一种非常容易出错的内存处理方法,就像我说的,您将使用RAII的一些变体。顺便说一下,你听起来像是在学习C++。我建议你从中学习。此外,如果您有问题,可以随时将问题发布到堆栈溢出上,以供将来参考。评论不是为了问全新的问题。现在我明白了,你做得对!函数返回一个指针,在该函数之外,您已经删除了它指向的内存。现在很清楚了,谢谢你的链接。你已经编辑了答案??:玛德:我很容易就错过了@安妮莎·考尔:不,我没有。根据我帖子下面的时间戳,我最后一次编辑我的答案是在1月10日。
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();
}
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();
}
void func1(int& oValue)
{
oValue = 1;
}
void func1(int oValue)
{
oValue = 1;
}