C++函数返回自由内存区间的对象的引用

C++函数返回自由内存区间的对象的引用
Effective C++
条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引用


 1  #include < iostream >
 2  #include < string >
 3 
 4  using   namespace  std;
 5 
 6  class  SimpleCat
 7  {
 8  public :
 9      SimpleCat( void );
10      SimpleCat( int  age, int  weight);
11       int  GetAge(){ return  itsAge;}
12       int  GetWeight(){ return  itsWeight;}
13 
14  private :
15       int  itsAge;
16       int  itsWeight;
17       // int itsAge=5; // 1>.\SimpleCat.cpp(14) : error C2864: “SimpleCat::itsAge”: 只有静态常量整型数据成员才可以在类中初始化
18 
19  public :
20       virtual   ~ SimpleCat( void );
21  };
22 
23  SimpleCat::SimpleCat( void )
24  {
25      cout << " SimpleCat constructor  " << this << endl;
26  }
27 
28  SimpleCat::SimpleCat( int  age, int  weight)
29  {
30      cout << " SimpleCat constructor  " << this << endl;
31      itsAge  =  age;
32      itsWeight  =  weight;
33  }
34 
35  SimpleCat:: ~ SimpleCat( void )
36  {
37      cout << " SimpleCat destructor " << this << endl;
38  }
39 
40  SimpleCat  & TheFunction();
41 
42  int  main()
43  {
44      SimpleCat myCat;
45      cout << myCat.GetAge() << endl; // 这个值区别于java不是赋初值为0的,而是一个随机的值
46  //     cout<<myCat.itsAge<<endl;
47 
48      cout << " ------------------------ " << endl;
49      SimpleCat  & rCat  =  TheFunction();
50       int  age  =  rCat.GetAge();
51      cout << " rCat is  " << age << " yeas old! " << endl;
52      cout << " &rCat:   " <<& rCat << endl;
53      SimpleCat  * pCat  =   & rCat;
54       // delete rCat; // 不能对引用使用delete
55      delete pCat;
56       // delete好像没有释放内存,怎么获取的还是原来的值
57       // 可能在这个内存区域存放的还是原来的?先new string后再调用也没变,与编译器有关还是什么??
58       for ( int  i  = 0 ;i < 10 ;i ++ )
59      {
60           // 想通过创建string对象来填充之前的内存区间,好像没用
61           string   * =   new   string ( " abcdefghijklmn " );
62      }
63 
64       // 这时问题来了,rCat.getAge()为123了
65      SimpleCat  * pSecond  =   new  SimpleCat( 123 , 444 );
66      
67      cout << " delete pCat后再使用rCat引用会发生什么问题??? " << endl;
68      cout << " delete pCat后 &rCat " <<& rCat << endl;
69      cout << " delete pCat后 rCat.age " << rCat.GetAge() << endl;
70 
71      cout << " -------------------------- " << endl;
72      SimpleCat myCat2  =  TheFunction(); // 这个会发生内存泄漏,在函数中申请的内存会得不到释放
73                                        // myCat2是通过默认的拷贝函数来进行初始化的
74      cout << " myCat2的地址是  " <<& myCat2 << endl;
75       return   0 ;
76  }
77 
78 
79  // 这个函数在返回时,是否会创建一个临时引用变量???
80  // TheFunctionTwo(SimpleCat &simpleCat)这个函数在传递参数时是否会创建一个临时的引用变量
81  // 临时的引用变量的作用域范围是什么
82  SimpleCat  & TheFunction()
83  {
84      SimpleCat  * pFrisky  =   new  SimpleCat( 5 , 9 );
85      cout << " pFrisky:  " << pFrisky << endl;
86       return   * pFrisky;
87  }
88 
89 
90 

函数TheFunction()的返回值被赋值给对SimpleCat类的一个引用,然后使用这个引用来获得对象的成员变量age的值
为了证明函数TheFunction()在自由存储区中创建的对象被赋给了函数main()声明的引用,对rCat采取取址运算,很明显,它显示了其引用的对象的地址,并且和自由存储区中的对象的地址相匹配。
这一切看上去都很正确,但是如何释放被占用的内存,对于引用是不能使用delete运算符的,一个笔记聪明的方法是声明另一个指针,并使用由rCat得到的地址对它进行初始化。这样做确实可以释放内存,避免了内存的泄漏,但是存在一个小问题,在delete pCat后,rCat引用又代表什么呢??引用必须是一个实际对象的别名;如果引用一个空对象的话(现在就是这种情况)那么程序就是无效的。。

注意:不能过分去强调一个使用对空对象的引用的程序,也行能通过编译,但是即使程序通过了编译,它仍然是病态的,而且执行结果也是不可预料的

关于这个问题,存在这3种解决方案
第1种是在第49行声明一个SimpleCat类对象,然后从函数TheFunction()中采取值传递的方式返回它的局部对象,这时不能在自由存储区来分配对象空间,不能使用new,
第2种是在函数TheFunction()中声明一个位于自由存储区中的SimpleCat类的对象,但是让函数返回一个指向内存区域的指针,然后完成对对象的操作,调用函数可以删除这个指针
第3种可行的方案,也是正确的,是在调用函数中声明对象,然后通过引用的方式把它传递给函数TheFunction()


也意味在main函数中不能这样使用了

你可能感兴趣的:(C++函数返回自由内存区间的对象的引用)