[C++]千万小心局部变量
来源:互联网 发布:淘宝上怎么不买香烟 编辑:程序博客网 时间:2024/05/07 17:18
千万小心局部变量
小心看好你的局部变量,尤其在这种情况下:
当你在一个function中声明了一个对象,然后你不遗余力地在对这个对象进行加工、进行操作,辛苦半天将他作为结果传出。好,编译,没问题,你似乎心满意足。可是别高兴太早,运行一下试试,哦,my god,内存引用错误,操作系统奉上了个无比可爱的小红叉叉,可是你却恨不得把他“一百遍”了。你有过这种经历吗?恩,好,让我们看看下面这段足以产生这样效果的代码:
#include
#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
- [C++]千万小心局部变量
- 嵌入式系统C语言编程小心使用局部变量
- 千万不能返回局部变量的引用??
- C语言局部变量
- [C++] 静态局部变量
- C语言局部变量
- C函数返回局部变量
- C局部变量返回值
- c 全局变量和局部变量
- C 函数返回局部变量
- C函数返回局部变量
- c 函数 返回局部变量
- C语言中的局部变量
- C/C++局部静态变量
- C函数返回局部变量
- C语言 -- 返回局部变量
- c全局和局部变量
- c语言返回局部变量
- 感受亲情
- 一天的演示
- ASP常用的函数
- 感激所有使你坚强的人
- hello?
- [C++]千万小心局部变量
- Java中static、this、super、final用法简谈
- RIA 体系中的设计模式-客户端组件到服务器的通讯(完)(翻译)
- 着色器和效果——3.2 像素着色器输入和输出
- 20040708今天我还活着
- 7月8日,原创网站访问量一天增加60多点
- Dell 电话技术支持工程师答用户问(转载)(暴笑)
- 2004.07.08,Thu - 周郎与黄盖
- 报关管理系统-生产企业