《条目十六》如何将vector和string的数据传给遗留的API
《条目十六》如何将vector和string的数据传给遗留的API
优秀的代码是可以延续的,所以并非所有的代码都是重构的,而且有时候重构会对整个系统影响较大,投入巨大,得不偿失。然而,也不必为了系统的稳定而抛弃先进和方便的技术。
正如如果你想在遗留的老代码中想传vector
和string
给形参是数组的接口,那么可以按以下的方法做:
接口:void dosomething(const char* ptr, size_t size);
传vector
给dosomething
接口方法:
- 1、&vec[0]———————-可行
- 2、vec.begin()—————不正确
- 3、&*vec.begin()————可行
方法1是ok,这是因为vector在内存上是连续分布的,和数组的内存分布是一致的,所以对vector的首元素取地址就是获得vector分配内存的首地址,通过首地址就可以得到连续的整块内存。
但是需要注意的是,vecto可能为空的情况,这样传参过去,形参是null, size为0,这样是错误的。可以在调用函数的时候就判断vector是否非空。
if(!vec.empty())
{
dosomething(&vev[0], vec.size());
}
这才是标准的做法。
方法2是不正确的,这样做可能是因为有人觉得vec.begin()得到的是指向vector容器的首地址的迭代器,就相当于是容器的地址。这里有个误区,迭代器不是指针,二者并非是等价的。
方法3是正确的,对比方法2,方法3先取得容器的首个元素的迭代器,然后解引用获得首个元素,再对其取地址。这样就等同于&vec[0]。
传string
给dosomething
接口方法:
- 1、
s.c_str()
——————正确 - 2、
&s[0]
——————————错误 - 3、
&*vec.begin()
————错误
string传参给char*需要注意了,由于string
的实现是多种多样的,string
对象的首个地址并非一定是字符串值的地址,详细的请看条目15的分析。所以直接传递string
的首元素的地址过去都是不正确,不管是直接对首元素取地址还是对取迭代器起始位置的解引用的地址,统统都不正确。
正确的做法是方法1,直接调用string.c_str()
接口,直接帮我们实现string
传参给char*
。
通过上面的分析知道,vector
可以很好的帮助我们实现容器传参给char*
的目的。从这可以展开来,可以把所有的容器先转换为vector
,然后再传递给以char*的形参的老接口。
但是在传递容器类型给以指针为形参的遗留API时需要注意,基本是传递const类型的,因为在函数内部对外部容器新增元素,容器是不知道它的size会发生变化的,因为不是通过容器本身改变新增元素,内部没有对size自增的,所以size真正没有改变。所以这样会造成容器数据的混乱,发生未定义行为。
上面举例子的都是以char*
为例子,真正情况下任何的基本类型的指针都是可以的。
看下面的例子:
void dosomething(const int* ptr, size_t size);
set<int> set;
for(int i = 0; i < 10; ++i)
{
set.insert(i);
}
vector<int> vec1(set.begin(), set.end());
if(!vec1.empty())
{
dosomething(&vec1[0], vec1.size());
}
list<int> list;
for(int i = 0; i < 10; ++i)
{
list.push_back(i);
}
vector<int> vec2(list.begin(), list.end());
if(!vec2.empty())
{
dosomething(&vec2[0], vec2.size());
}
《条目十六》如何将vector和string的数据传给遗留的API的更多相关文章
- 条目十三《尽量使用vector和string来代替使用数组》
条目十三<尽量使用vector和string来代替使用数组> 数组在现代编程语言中基本都存在,应用可谓广泛,不可或缺,虽然在一些语言中(go)有切片等数据结构,但是数组还是存在的. 但是在 ...
- 【S16】了解如何把vector和string数据传给旧的API
1.尽量使用vector和string替换数组,但是老的代码还是使用数组.如果老的接口期望是数组,怎么办? 需要把vector和string,暴露出数组接口,也就是第一个元素的地址. 2.考虑方法Do ...
- robotframework的学习笔记(十六)----robotframework标准库String
官方文档:http://robotframework.org/robotframework/latest/libraries/String.html Introduction A test libra ...
- (十六)java中的String
String:字符串类型,是java中最常用的引用类型,String是不可变的,java.lang.String是由final修饰,此类不可被继承. String是不可变的,指的是字符串一旦创 ...
- 【第十六章】 springboot + OKhttp + String.format
模拟浏览器向服务器发送请求四种方式: jdk原生的Http包下的一些类 httpclient(比较原始,不怎么用了):第一章 HttpClient的使用 Okhttp(好用,推荐) retrofit( ...
- kuangbin专题十六 KMP&&扩展KMP HDU3347 String Problem(最小最大表示法+kmp)
Give you a string with length N, you can generate N strings by left shifts. For example let consider ...
- leecode第十六题(最接近的三数之和)
class Solution { public: void quick_order(vector<int>& num, int star, int en)//快排 { int st ...
- LeetCode第十六题-找出数组中三数之和最接近目标值的答案
3Sum Closest 问题简介: 给定n个整数的数组nums和整数目标,在nums中找到三个整数,使得总和最接近目标,返回三个整数的总和,可以假设每个输入都只有一个解决方案 举例: 给定数组:nu ...
- JAVA之旅(十六)——String类,String常用方法,获取,判断,转换,替换,切割,子串,大小写转换,去除空格,比较
JAVA之旅(十六)--String类,String常用方法,获取,判断,转换,替换,切割,子串,大小写转换,去除空格,比较 过节耽误了几天,我们继续JAVA之旅 一.String概述 String时 ...
随机推荐
- webapi help文档 添加测试功能
在做webapi项目的时候 webapi为我们提供了help文档,开发者可以参考这个文档,但是这个文档缺少测试功能,如果加上一个测试的功能就更加方便了 于是就研究了下写了一段代码,代码比较简单,只要将 ...
- Animation组件
[Animation组件] Animation是Unity3D中老的动画组件,从4.x起已全面被MecAnim中的Animator组建所替代.但是4.x仍保留了Animation组件,所以了解此组件还 ...
- docker swarm && compose 示例
docker swarm 创建docker swarm集群 //master节点操作 docker swarm init --advertise-addr materip //node节点操作 -1x ...
- C. Ray Tracing——披着搜索外衣的扩展欧几里得
[题目大意] 给你一个n*m的矩形,光线从(0,0)出发,沿右上方向以每秒根号2米的速度运动,碰到矩形边界就会反弹(符合物理规律的反弹),询问k个点,这些点都在矩形内部且不在矩形边界上,求光经过这些点 ...
- VMware设置及linux静态ip设置
1. VMWARE虚拟机NAT模式上网设置 1.1. VM虚拟机设置 1.1.1. 虚拟机全局设置 启动虚拟机选择[虚拟网络编辑器] 如果需要管理员权限点[更改设置],没有提示这忽略这一步 选 ...
- 61-结点选择(树形dp)
http://lx.lanqiao.cn/problem.page?gpid=T14 算法训练 结点选择 时间限制:1.0s 内存限制:256.0MB 问题描述 有一棵 n 个 ...
- Docker学习之路(一)
容器简介 管理程序虚拟化(hypervisor virtualization, HV)是通过中间虚拟运行于物理硬件之上.而容器是直接运行在操作系统内核之上用户空间.因此,容器虚拟化运行也成为“操作系统 ...
- 【Head First Java 读书笔记】(三)primitive主数据类型和引用
认识变量 变量有两种:primitive数数据类型和引用. 声明变量 Java注重变量.它不会让你将浮点数类型变量放进整数类型的变量中,除非你先跟编译器确认过数字可以损失掉精确度. 为了要让类型安全能 ...
- SNMP协议学习笔记
什么是SNMP协议? SNMP协议是以UDP为基础的应用层协议,全称为 简单网络管理协议,用于网络管理系统与被管设备(路由器,交换机,服务器等设备)进行通信. 应用场景 随着网络设备的增多,需要单独的 ...
- Oracle ERP系统借贷关系表
Oracle ERP系统借贷关系表 成本核算会计信息归纳 按照事务处理的来源类型归纳. 一. 采购接收入库和退货: 1.接收: 借:材料采购 (订单价格) 贷:应计负债 (订单价格) 2.入库: ...