环境是linux系统centos7版本下的4.8版本的g++
首先看代码
思考一下下面两段toHex代码,返回char*是错误代码还是返回string是错误写法,报什么错。
这里假设已经包含各种头文件。
snprintf函数:它会将格式化的数据输出到buffer所指向的空间中,最多输出size个字节(包含’\0’结束符)。
该函数功能时将key值格式化输出到buffer数组内,然后返回并执行 cout<<toHex();
char* toHex(char* key)
{
char buffer[64];
snprintf(buffer,sizeof(buffer),"%s",key);
return buffer;
}
string toHex(char* key)
{
char buffer[64];
snprintf(buffer,sizeof(buffer),"%s",key);
return buffer;
}
int main()
{
cout<<toHex("abc")<<endl;
return 0;
}
解释
当key为char*类型时
- 使用char*,我们传入的是字符串常量,而在C++11中已废弃这种隐式转换,必须进行显式转换,所以编译器报弃用错误,理由是c中的把const 不能被修改,而char*可修改。
-
为了修改上面的错误,我们可以将char* 改为const char*类型。
即函数定义为char* toHex(const char* key)
而后我们再发现,又有一个新的错误出现:返回野指针
因为buffer是局部变量,其中的内容在函数栈帧销毁后随之销毁。我们返回该地址指针,打印它的值毫无意义,它的值可能已经被覆盖,这就是野指针中的一种情况。 -
为什么string作返回值不会出现这种情况呢?
string作为c++中标准库的一员,返回string时,会生成一个临时对象并进行深拷贝,拷贝内容使string内部管理的内存有效,避免了问题的产生。返回char*只是生成的临时对象只是拷贝了指向那块儿空间的地址,这毫无意义。
这就是char*与string在返回时的一个非常关键的差异 - string的深拷贝机制可以避免内存无效访问问题。