什么时候需要删除由函数返回的指针
created by jsjwql http://blog.csdn.net/jsjwql/
最近在做项目的时候,调用了很多第三方的API, 这些API 有很多返回char *, const char *, 有时需要delete 返回的字符串,有时不能,一删则错,晕,这有什么规则吗?
让我们先看看几个例子
// Return Pointer.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdlib.h"
#include "string.h"
//Array
char* test1()
{
char p[] = "test"; //静态存储区上,可以被修改,不是堆上,所以不能delete掉
return p;
}
const char* test2()
{
const char p[] = "test"; //const变量, 全局数据
return p;
}
char* test3()
{
static char p[] = "test"; //静态存储区上
return p;
}
//pointer to const
char* test4()
{
char *p = "test"; //p指向常量字符串,返回字符串指针不能被编辑
return p;
}
const char* test5()
{
const char *p = "test"; //指向常量的指针
return p;
}
char* test6()
{
static char p = 't'; //static, 全局数据
return &p;
}
char* test7()
{
return "test"; //常量
}
//pointer to heap
char* test8()
{
char *p= new char[10]; //heap
strcpy(p, "test");
return p;
}
const char* test9()
{
char *p= new char[10]; //heap
strcpy(p, "test");
return p;
}
char* test10()
{
static char *p = new char[10]; //heap
strcpy(p, "test");
return p;
}
int _tmain(int argc, _TCHAR* argv[])
{
//Array
char *str1 = test1();
*str1 = 'T';
//delete str1;
const char *str2 = test2();
//*str2 = 'T';
//delete str2;
char *str3 = test3();
*str3 = 'T';
//delete str3;
//pointer to const
char *str4 = test4();
//*str4 = 'T';
//delete str4;
const char *str5 = test5();
//*str5= 'T';
//delete str5;
char *str6 = test6();
*str6 = 'T';
//delete str6;
char *str7 = test7();
//*str7 = 'T';
//delete str7;
//pointer to heap
char *str8 = test8();
*str8 = 'T';
delete str8;
const char *str9 = test9();
//*str9 = 'T';
delete str9;
char *str10 = test10();
*str10 = 'T';
delete str10;
return 0;
}
我列举了很多情况,但是可以总结成一下几点:
1. 仅仅从函数的声明不能判断返回的字符串是否需要delete,这是需要添加comment说明该情况。
2. 变量无非为分配在stack, heap, global等区域, 只有分配在heap上的才能被delete,不管函数返回的是char*, 还是const char*。
其它情况都不能删除,需要一提的是stack分配的变量在离开函数体的时候就已经不存在了。
3. 仅仅从返回的值是char*, 也不能断定改函数返回的值是可以被修改的,当然一个好的函数声明在返回字符串不能被修改的情况下最好还是声明成const char*
4. 想从函数中返回有效指针,可以返回const,static,heap上的数据。我指的数据不是指指针,而是指针指向的数据类型。
想test6如果改成
char* test6()
{
char p = 't';
static char *q= &p;
return q;
}
显然不行
5. 还有常见的做static_cast, dynamic_cast等相应指针转换的时候,由于没有在heap中开辟数据,所以不需要delete它
void test()
{
int i = 1;
void *p = &i;
int *j = static_cast<int *>(p);
delete j; //这里不能delete,由于j不在heap上
}
如果稍加修改
void test()
{
int *i = new int('a');
void *p = i;
int *j = static_cast<int *>(p);
delete j; //这里j虽然指向heap上的对象,但是也不能
//delete, static_cast并没有在heap上生成新的对象,、//delete的任务是i负责,否则重复删除
delete i;
}
有一种转换情况需要注意delete,就是char* 与w_tchar *之间转换的时候,需要new出新的空间(当然你也可以把char*所占用的内存释放掉再在此基础上new出w_tchar*来),有新的对象出现在heap上了。
6. 总之已经话,我们不是delete指针,而是delete堆上面的对象,而这个对象往往是通过指针来操作的。