C++返回局部变量的引用的问题

结论:

(1)不能返回局部变量的引用给一个引用变量。

(2)但是如果返回引用给一个相关的非引用变量的话是可以的.

原因如下:

问题一:
返回一个局部变量的引用。如:
int& ABC()
{
  int n = 5;
  return n;
}
void main()
{
  int x;
  x=ABC();
  cout<<x<<endl;
}
为什么这里能接收到 返回局部变量的引用呢?局部变量n没有被销毁吗?

解释:

(1)

  所谓不能返回局部变量,是指局部变量在栈空间中分配内存,函数返回时栈指针回退,当主调函数继续调用其它被调函数时,栈指针上移,上一次函数调用所分配的空间会被本次调用覆盖,如果此时再引用原来的局部变量就会出现不可预见的结果。
  所以局部变量在函数返回时并不是被销毁而是相当于可被再次利用。所以如果第一题你在cout<<x<<endl;前调用一个函数,此函数大量分配局部变量,后面的输出值必变!

(2)
  如果把返回的引用赋给变量是无论怎么都不会变的,因为返回时进行了变量的复制(不一定是调用构造函数),要改变其实我上面已经说了只要在cout<<X前调用一个函数且函数内定义了局部变量即可:
  int x= ABC(); 
  test();
  cout<<x;

  void test()
  {
    int a=8;
  }
这样X的输出将是8,下题类似不再举例.

另外一种解释:

  函数退出时局部变量出栈,对象肯定是销毁了。销毁指的是将那块内存标为空闲供其它变量使用,而该内存上的值仍然存在。释放后那块内存并不是马上就被其他地方占用,根据实际情况起码会空闲一会,可能是一瞬间。如果你的程序较复杂,那这块内存可能很快就再次被使用,如果程序很简单,可能在很长一段时间内都是空闲。所以在函数返回后将变量的值马上赋值给另外一个变量,局部变量已经销毁了,这块内存上的值还没来得及被修改,所以你的外部变量获得了一个正确的值。

所以你的结果正确并不代表变量没有被销毁。就像第一种解释一样,如果第一题你在cout<<x<<endl;前调用一个函数,此函数大量分配局部变量,即占用那段内容,其值必变,这已经经过我验证。

  用引用和用对象的区别在于,对象需要构造,而引用只是个别名,类似指针(引用在C++底层其实就是指针),故如果将返回引用的函数赋值给某个引用是不行的,因为它指向内存可能已经被其他内容占据了。而如果把返回的引用赋给变量是可以的,因为返回时进行了变量的复制。

看如下例子:

#include <iostream>
using namespace std;
int& fun()
{
   int i = 100;
   return i;
}
void test()
{
   int i = 0;
}
int main()
{
  // int& a = fun();//返回的是局部变量i的引用,即地址,有问题。相当于int &a = i;

  int a=fun();//返回的是局部变量i的值,没有问题,相当于int a = i;
  // test(); //此处由于fun后没有其他代码,所以输出值没问题,若将test函数打开,则a的值会有问题。
   cout << a << endl;
   return 0;
}

例子2:

#include <iostream>
using namespace std;

class Complex
{
public:
Complex(double r=0,double i=0)
{
real=r;imag=i;
}
Complex(const Complex& c);
Complex& operator+(Complex &);
void display( );
private:
double real, imag;
};
Complex::Complex(const Complex& c)
{
real=c.real;
imag=c.imag;
}
Complex& Complex::operator+(Complex &c2)
{
int a=1;
Complex c;
c.real=real+c2.real;
c.imag=imag+c2.imag;
return c;
}
void Complex::display( )
{
int xxxx=1;
cout <<"(" <<real <<"+" <<imag <<"i)" <<endl;
}

int main( )
{
double x, y;
cin>>x>>y;
Complex comp1(x,y),comp2(y,x),comp3;
comp1.display( );
comp2.display( );

comp3=comp1.operator+(comp2); //用对象 接收函数返回的引用 是正确的
Complex& p=comp1.operator+(comp2); //用对象的引用 接收函数返回的引用 是错误的

p.display();
comp3.display();
return 0;
}

时间: 2024-10-07 12:46:49

C++返回局部变量的引用的问题的相关文章

实战c++中的string系列--函数返回局部变量string(引用局部string,局部string的.c_str()函数)

当函数返回字符串的时候,我们可以定义返回string和string&. 1写一个返回string引用的函数 std::string & TestStringReference() { std::string loal_str = "holy shit"; return loal_str; } 这个函数当然是错误的,编译器会提示我们: 返回局部变量或临时变量的地址: loal_str 即不能返回局部变量的引用. 2写一个返回string的函数(函数返回局部变量string

函数返回局部变量的问题

1.函数可以返回局部变量 当函数的局部变量作为函数的返回值时,其实是不知道是谁(是程序?)会自动生成一个变量的副本即拷贝作为函数的返回值,而原有的局部变量将被销毁. 注意函数不可以返回局部变量的地址或者某个指针,以为当函数运行完了(这里改咋说),系统会回收这块地址,因此这个地址里面 的东西也就没有意义了. 静态变量可以返回指针. 2. int a[] = {1, 2}; return a; 此时也会返回指针a的一个拷贝,若a的地址值为0x002345FC,则0x2345FC是能够成功返回的.当r

C++编程经验-返回局部变量的讨论(转)

返回局部变量没问题 如果返回局部变量有问题,函数的意义还有吗? 全局变量还用返回吗? 返回指向局部变量的指针才有问题, 函数退栈之后,局部变量消失, 指针将指向未知区域,所以出现问题. 返回局部变量的引用也是绝对不可以的. 引用只是变量的一个别名,变量本体都不存在了,引用当然也没有任何意义. 还有,如果是堆空间,可以返回,即在函数中用new申请的空间,是可以返回的. 但是一般的情况下,好的风格是: 尽量在同一个作用域内成对使用new   和delete,(也即不要返回堆空间),因为如果不是这样,

【转】函数返回局部变量

(看到C++ Primer(P.225)“return reference to local object”时有点懵,然后找到了这篇博文.) 一般的来说,函数是可以返回局部变量的. 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了.因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错.但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错.因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错.准确的来

[转]C++编程经验-返回局部变量的讨论

返回局部变量没问题 如果返回局部变量有问题,函数的意义还有吗? 全局变量还用返回吗? 返回指向局部变量的指针才有问题, 函数退栈之后,局部变量消失, 指针将指向未知区域,所以出现问题. 返回局部变量的引用也是绝对不可以的. 引用只是变量的一个别名,变量本体都不存在了,引用当然也没有任何意义. 还有,如果是堆空间,可以返回,即在函数中用new申请的空间,是可以返回的. 但是一般的情况下,好的风格是: 尽量在同一个作用域内成对使用new   和delete,(也即不要返回堆空间),因为如果不是这样,

返回局部变量

返回局部变量 一般的来说,函数是可以返回局部变量的. 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了.因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错.但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错.因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错.准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的). 1. 返回局部变量的值 可以有两种情况

C++ Primer 学习笔记_17_从C到C++(3)--引用、const引用、引用传递、引用作为函数返回值、引用与指针区别

欢迎大家阅读参考,如有错误或疑问请留言纠正,谢谢 一.引用 1.引用是给一个变量起别名 变量: 名称 空间 引用: 引用不是变量 引用仅仅是变量的别名 引用没有自己独立的空间 引用要与它所引用的变量共享空间 对引用所做的改变实际上是对它所引用的变量的改变 引用在定义的时候必须要进行初始化 引用一经初始化,不能重新指向其他变量 2.定义引用的一般格式: (1)类型  &引用名 = 变量名: (2)例如: int a=1; int &b=a; // b是a的别名,因此a和b是同一个单元 (3)

C++11函数返回右值引用

我们定义了一个可以传入右值引用的构造函数的类B,在使用std::move的时候,我们非常容易犯一个错误.看下面的代码: class B { public: B() :s(10), ptr(new int[s]) { std::cout << "default constructor" << std::endl; for (int i = 0; i < s; i++) { ptr[i] = i; } } B(const B& b) :s(b.s) {

《C++ Primer》学习 之 返回数组的引用(返回数组的指针,方法与之相同)

/* 返回数组的引用(返回数组的指针,方法与之相同) 共四种方法(在下面示例程序中,调用其中一种方法时,需要将其他三种方法注释掉)*/ 1 #define _CRT_SECURE_NO_WARNINGS 2 #define HOME 3 #include <iostream> 4 #include <stdexcept> 5 #include <ctype.h> 6 #include <locale> 7 #include <iterator>