[C++]千万小心局部变量

原创 2004年07月08日 21:02:00

千万小心局部变量

小心看好你的局部变量,尤其在这种情况下:
当你在一个function中声明了一个对象,然后你不遗余力地在对这个对象进行加工、进行操作,辛苦半天将他作为结果传出。好,编译,没问题,你似乎心满意足。可是别高兴太早,运行一下试试,哦,my god,内存引用错误,操作系统奉上了个无比可爱的小红叉叉,可是你却恨不得把他“一百遍”了。你有过这种经历吗?恩,好,让我们看看下面这段足以产生这样效果的代码:

#include  <iostream>

#include  <cstring>

using namespace std;

class String
{
public:
                     String()
                     {
                     }

                     String(char* str)
                     {
                                 size_t len = strlen(str);
                                 p = new char[len + 1];
                                 strcpy(p,str);
                     }

                     String(const String& rhs)
                     {
                                 size_t len = strlen(rhs.p);
                                 p = new char[len + 1];
                                 strcpy(p,rhs.p);
                     }

                     void print()
                     {
                                 char* pp = p;
                                 while(*pp != '/0')
                                 {
                                       cout << *pp;
                                       ++pp;
                                 }
                     }

                     char* p;
};

int main()
{
         String str1("Hello,world!/n");
         String str2(str1);
         str1.print();
         str2.print();
         return 0;
}

恩~,程序模拟了string的行为,很简单不是吗?运行一下,似乎跑得不错啊。好,我现在想这样操作我的string:
String str3;
str3 = str1 + str2;

怎么办?很自然的想法就是为我的程序添加一个对运算符“+”的重载函数。这样写,看有问题吗:

String operator +(const String& rhs)
{
                     String temp;
                     size_t len = strlen(p) + strlen(rhs.p);
                     temp.p = new char[len];
                     strcpy(temp.p,p);
                     strcat(temp.p,rhs.p);
                     return temp;
}


将下面的main替换掉原来的main函数:

int main()
{
                     String str1("Hello,world!");
                     String str2(str1);
                     String str3;
                     str3 = str1 + str2;?
                     cout << "/nstr1: ";
                     str1.print();
                     cout << "/nstr2: ";
                     str2.print();
                     cout << "/nstr3: ";
                     str3.print();
                     cout << endl;
                     return 0;
}

运行一下,好,没问题!下面我们来回顾一下我们的程序,什么?你是不是发现我们自己在堆上new出来的内存用完后都没释放呢!这怎么能行?!于是,很自然地,我们为我们的程序添加了一个析构函数:

~String()
{
         delete[] p;
}

编译……,OK!没问题!
运行……,oh god!怎么了?小红叉叉!!!
我在文中开始的时候所描述的一幕终于发生了,是不是期待已久啊。呵呵,你可能已经发现了,问题就在+操作符重载函数里面,因为他返回了一个局部变量。当这个局部变量被传出去后,在+操作符重载函数的他本身就销毁了。所以可以判断这个赋值号“=”并没有把对象中的内容一一拷贝给目标。所以,一种办法是重载一下“=”,而另一种更简单的方法便是将str3声明为:String str3 = str1 + str2;从而直接利用拷贝构造函数完成这个任务,试试看,程序是不是又能跑了?下面我们来看看另一种解决方案,我们来重载一下“=”,我们为我们的程序中添加下面的代码:

void operator =(const String& rhs)
{
                  size_t len = strlen(rhs.p);
                  p = new char[len + 1];
                  strcpy(p,rhs.p);
}

编译运行一下看看,呵呵,我们的程序又恢复了活力!

所以,我们看到,在一个function中返回一个局部变量,他会在他本身被销毁之前copy自身,从而将内容赋给目标。因此,你需要重载"="并提供拷贝构造函数;而如果你试图在一个function中返回一个局部变量的指针,那你麻烦大了。这个指针在他本身被销毁之前copy自身(注意这是个地址信息),然而目标再次想访问他的时候,他的原来那份地址已经被销毁了,我们的目标并没有得到他的具体信息,我们当时得到的仅仅是他的一个地址信息而已。重点是:pass-by-value便是调用copy constructor的同意词;initialization初始化是由constructor完成,而assignment赋值是由operator=完成。所以,到此为止,一切都清净了...

小的菜鸟一只,不知天高地厚,发拙作于此,欢迎各位达人拍砖!

                                                                                       sun

                                                                                       2004-7-15

大事大约,小事小心

大事大约,小事小心
  • wyzxg
  • wyzxg
  • 2009年10月05日 21:47
  • 1064

C++中不应该返回局部变量的地址

在Effective C++中明确指出:不应该返回
  • tujinqiuqq85948239
  • tujinqiuqq85948239
  • 2014年05月27日 22:36
  • 810

c++函数返回局部变量

char* func() { char arr[] = "Hello,World\n"; // arr[] 所有元素保存在栈内存上 return arr; // 返回局部变...
  • sjtu_chenchen
  • sjtu_chenchen
  • 2015年08月22日 15:22
  • 776

C++ 参数传递, 局部变量内存 释放问题

ValueMap vm ; vm.insert(make_pair("mySex",Value("male"))); vm["myname"] = Value("William"); vm["...
  • ywl102402
  • ywl102402
  • 2014年08月03日 09:05
  • 732

C++中的对象作为局部变量时的析构问题

在一个函数内,申明一个局部类变量。则这个变量什么时候析构呢? 并不是在函数退出、释放栈空间时候析构消亡,而是在大括号终结时。举例如下: #include #include class TT { ...
  • zhouxinyu1cp
  • zhouxinyu1cp
  • 2014年12月25日 10:13
  • 263

C++里类中定义对象与定义局部变量的问题

如果我定义了一个Cat类: class Cat { public: Cat();                                                    //默认...
  • wanzi0933
  • wanzi0933
  • 2015年11月06日 10:55
  • 785

关于C/C++: 在函数外存取局部变量问题( 精辟 )

今天上网看到一个很好玩的也很有深度的C++问题,代码是这样的:          #include int * fun() {     int a =5;     return (...
  • shanshanpt
  • shanshanpt
  • 2012年03月16日 16:27
  • 1056

c/c++函数返回局部变量数组

在c/c++中,是不应该返回局部变量数组的 这是因为在函数中,局部变量是存储在栈内存中的,而函数的返回是值拷贝 因此数组返回实际是返回指向栈内存中这个原数组的首地址,但是函数结束后 该内存是会被...
  • qq_16097611
  • qq_16097611
  • 2016年07月13日 11:24
  • 831

C++局部变量指针保持在List,Vector中使用的问题

最近做个一个模型处理系统,需要处理不同类型和种类的大量的模型数据,因此采用了List和vector保持识别的不同类型的大量数据,然后分别处理模型,由此遇到如下问题: 这里以一个实例说明,数据类型存储...
  • pizibing880909
  • pizibing880909
  • 2014年09月25日 21:17
  • 1130

不要返回局部对象的引用

在一个函数返回值为引用时,千万不要返回局部变量的引用。 看下面的例子: class Data { Public:     Data();     ~Data();     ...
  • liupeng1985
  • liupeng1985
  • 2014年04月12日 15:25
  • 814
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[C++]千万小心局部变量
举报原因:
原因补充:

(最多只允许输入30个字)