关于在函数调用时传递string引用的必要性
其实我想只要能看到这篇博客的朋友,又是学过C/C++的都应该知道,如果一个对象需要作为函数调用的一个参数,同时对象分配的内存又非常大的时候,应该使用const T&来作为参数。
虽然知道这一点,但是我还是经常会在传递string参数的时候,直接不使用引用,今天仔细看了一下string的写时copy,突然想到,大家看到string就要求传递引用会不会只是一种惯性驱使呢,string的copy真的会把分配的内存全部copy一遍?
我们其实做一个简单的实验就知道了,代码如下:
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
void test1(string c)
{
printf(\"c[%u]\\n\",c.c_str());
}
void test2(const string& d)
{
printf(\"d[%u]\\n\",d.c_str());
}
void test3(const string e)
{
printf(\"e[%u]\\n\",e.c_str());
}
int main(int argc, const char *argv[])
{
string a = \"one\";
string b = a;
printf(\"a[%u]b[%u]\\n\",a.c_str(),b.c_str());
test1(a);
test2(a);
test3(a);
a=\"s\";
printf(\"a[%u]b[%u]\\n\",a.c_str(),b.c_str());
return 0;
}
输出结果:
a[4009044]b[4009044]
c[4009044]
d[4009044]
e[4009044]
a[4009068]b[4009044]
答案应该很明确了,有些语言规范所恪守的string必须传递引用其实是有些教条主义了。
其实不只是string,只要将自己实现的类的copy构造函数增加计数器判断,也可以达到一样的效果。
============================我是华丽的分割线===============================
对string其实还有一种用法,即不作为字符串而作为buf管理器来用(突然觉得很像python的str类型,并不是以\\0来决定结尾)
如下用法
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
int main(int argc, const char *argv[])
{
string a = \"s\";
printf(\"aptr[%u]\\n\",a.c_str());
printf(\"a[%s][%u]\\n\",a.c_str(),a.size());
a.resize(10);
printf(\"aptr[%u]\\n\",a.c_str());
printf(\"a[%s][%u]\\n\",a.c_str(),a.size());
for (int i = 0; i < a.size(); i++) {
printf(\"%02x \",a[i]);
}
memset((char*)a.c_str(),0,a.size());
printf(\"\\n\");
for (int i = 0; i < a.size(); i++) {
printf(\"%02x \",a[i]);
}
printf(\"\\n\");
printf(\"a[%s][%u]\\n\",a.c_str(),a.size());
string b = a;
printf(\"aptr[%u]bptr[%u]\\n\",a.c_str(),b.c_str());
printf(\"b[%s][%u]\\n\",b.c_str(),b.size());
return 0;
}
输出结果:
aptr[4009044]
a[s][1]
aptr[4009068]
a[s][10]
73 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
a[][10]
aptr[4009068]bptr[4009100]
b[][10]
从上面的结果,我们可以得到如下几个信息:
1.string在resize的时候,会重新申请新的内存,并将原来的内存copy到新内存上。
2.copy构造函数中也不是以\\0为拷贝的结束符,而是将整个size()都进行copy。
3.直接使用resize破坏了string内部的计数,所以在string b = a的时候,b重新分配了一块全新的内存而不是和a共用。
由上面3点可以看出,string完全可以用来做一个简单的buf管理器,不过一旦决定将string用作buf就不要在使用字符串的方法,如==来判断两端buf是否相等之类,否则会有很多奇怪的错误。不过如果担心b和a不小心公用同一块内存的话,可以使用resize方法来为b自己copy出一份内存出来。
OK,目前关于string的理解就这么多,如果有不对之处还请多多指教。
建议继续学习:
- perl模块Getopt::Std用法及实例-从命令行读取参数模块 (阅读:5884)
- 千万不要把 bool 当成函数参数 (阅读:4094)
- 不定参数的应用 function(fmt, …) (阅读:3996)
- 函数式编程 (阅读:3677)
- JavaScript的5种调用函数的方法 (阅读:3601)
- 一个简单的stl中string的split函数 (阅读:3262)
- C 语言中统一的函数指针 (阅读:3033)
- String,StringBuffer,StringBuilder的区别 (阅读:3013)
- C语言函数实现的另类方法 (阅读:2909)
- Java将Object对象转换为String的总结合集 (阅读:2925)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:Dante 来源: Vimer
- 标签: string 函数 参数
- 发布时间:2010-06-24 09:46:10
- [54] IOS安全–浅谈关于IOS加固的几种方法
- [52] android 开发入门
- [52] 如何拿下简短的域名
- [51] 图书馆的世界纪录
- [49] Oracle MTS模式下 进程地址与会话信
- [49] Go Reflect 性能
- [47] 【社会化设计】自我(self)部分――欢迎区
- [46] 读书笔记-壹百度:百度十年千倍的29条法则
- [35] 程序员技术练级攻略
- [29] 视觉调整-设计师 vs. 逻辑