不要在公共接口中传递STL容器
最近的一个项目,是开发一个framework,提供给公司内部不同的产品线使用。 之间遇到的一个问题,就是STL容器的使用, 而结论是不要在公共接口中传递STL容器:
这里说的STL容器,但主要则是指容器,字符串类,但其实可以推广到在STL中提供的任何类型,
这里说的公共接口,是指需要暴露给客户的sdk头文件,包括函数签名,或者类成员变量;
也可以说,不要在暴露给客户的头文件中包含STL的头文件。
原因分析
为什么有这个结论,我们可以从几个方面来论述:
客户端使用的STL版本可能不同
因为STL作为标准库,Framework编译的时候使用的STL,与客户端编译的时候使用的STL,版本是有可能不一样的,比如Framework使用VC8编译发布,而客户代码使用VC10编译使用,那么Framework所理解的STL容器,与客户端代码所理解的STL容器,在内存布局上,数据表示上是有可能不一样的,出错也就不可避免了。
编译选项
即使Framework和客户端使用的是同一个版本的STL,但是如果编译选项不一样,也可能导致其不一致性,自然也会出错。
静态变量
即使版本一致,编译选项一致,仍然是不安全的,因为STL容器的实现中,有可能使用了静态变量,而在Framework模块和客户端模块中,虽然由于模板扩展产生的两份代码总体上是一致的,但都各自维护了一份静态变量,从而造成了内部状态的不一致性。
客户端的STL被自定义
但从文件的角度来看,在客户端包含的STL头文件实现,可以是完全不同于标准的 - 只要其接口和标准保持一致。 比如客户那边使用的STL在内存管理方面有特殊需求,改写了默认的allocator,那么内存必然会出问题;比如客户在实现中加入了其他成员变量,那么内存布局必然也不一致。
虽然,微软这篇文章提到导出vector是安全的,但是根据上面的分析,这应该是不安全的做法。
可选方案
但事实上,你还是可能存在这种需求的 - 你需要容器类的函数参数或者返回值,你可能也需要容器类的类成员变量,那么如何解决?
对于前者,我们可以针对具体的类型封装一个具体的容器类,内部还是可以使用STL container的;
对于后者,我们可以用一些办法,防止STL容器出现在头文件中;
解决的方法,可以有以下几种:
提供自己的容器类
这是最彻底,最直接的方法,但是提供一套与STL相当的模板容器类需要蛮大的工作量,而且明显是重复制造轮子了。 要注意,这里简单的对STL容器进行封装是行不通,因为模板不支持分离编译,这么做还是会把STL容器带入公共接口。
PImpl
PImpl模式当然很强大,当然可以解决这个问题,但是此处如果仅仅是为了隐藏容器类,难免杀鸡用牛刀,还引入了不必要的间接层与繁琐的脚手架代码。
使用void*作为数据成员,而后强制转换为容器类
不安全也太丑陋,用起来也繁琐,每次都要cast以下,除非别无他法,是在不应该考虑这个方案。
前置声明STL容器
这个方法在VC9中是可以工作的,但是根据C++标准: 17.4.3.1 Reserved names,这种做法是未定义的:
“ It is undefined for a C++ program to add declarations or definitions to namespace std or namespaces within namespace std unless otherwise specified”
自定义结构体封装容器并前置声明
这个方案是这样的:
//头文件
struct PublicClassData;
class PublicClass{
public:
PublicClass();
private:
PublicClassData* m_pData;
}
//实现文件
struct PublicClassData
{
vector<int> _array;
map<string, int> _map;
};
PublicClass::PublicClass()
{
m_pData = new PublicClassData;
}
当然,需要注意的是我们需要遵循:rule of three,提供析构,赋值与拷贝构造函数以管理内存。
这个方案相对来讲比较简洁,应该说是现有方案的最有实践性的一个。
结论
所以,结论就是不要在DLL/SO的公共接口中使用STL容器,如果你确实需要,那么请用自定义结构体封装容器并前置声明的方式隔离STL容器!
不要在公共接口中传递STL容器的更多相关文章
- DLL中传递STL参数(如Vector或者list等)会遇到的问题[转载]
最近的一个项目中遇到了调用别人的sdk接口(dll库)而传给我的是一个vector指针,用完之后还要我来删除的情况.这个过程中首先就是在我的exe中将其vector指针转为相应指针再获取vector中 ...
- DLL中传递STL参数,vector对象作为dll参数传递等问题(转)
STL跨平台调用会出现很多异常,你可以试试. STL使用模板生成,当我们使用模板的时候,每一个EXE,和DLL都在编译器产生了自己的代码,导致模板所使用的静态成员不同步,所以出现数据传递的各种问题,下 ...
- 如何优雅的传递 stl 容器作为函数参数来实现元素插入和遍历?
问题背景 开始正文之前,做一些背景铺垫,方便读者了解我的工程需求.我的项目是一个客户端消息分发中心,在连接上消息后台后,后台会不定时的给我推送一些消息,我再将它们转发给本机的其它桌面产品去做显示.后台 ...
- Mybatis接口中传递多个参数
1.接口 public interface MemberMapper { public boolean insertMember(Members member); public Members sel ...
- C++ STL 容器之栈的使用
Stack 栈是种先进后出的容器,C++中使用STL容器Stack<T> 完美封装了栈的常用功能. 下面来个demo 学习下使用栈的使用. //引入IO流头文件 #include<i ...
- stl中顺序性容器,关联容器两者粗略解释
什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器.很简单,容器就是保存其它对象的对象 ...
- STL中的set容器的一点总结
1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...
- 【转】c++中Vector等STL容器的自定义排序
如果要自己定义STL容器的元素类最好满足STL容器对元素的要求 必须要求: 1.Copy构造函数 2.赋值=操作符 3.能够销毁对象的析构函数 另外: 1. ...
- 【转】 STL中的set容器的一点总结
1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...
随机推荐
- wampserver 2.2装好后80端口未被占用,却打不开localhost
在windows server 2003中装好wampserver2.2后打不开localhost,点击服务全部启动(颜色是橙色)也是打不开,我解决的原因是:安装mysql中sevice中的安装测试服 ...
- Python之路第八天,基础(9)-面向对象(下)
类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...
- 1 起步-Pro Git---VCS比较、git基本原理、git配置
本地版本控制系统 集中化的版本控制系统 诸如 CVS,Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务 ...
- SQL Server 无法启动的 4 种原因
SQL Server 无法启动的原因定位.首先要知道SQL Server 启动的过程. 第一步: 读取注册表,创建log文件.检测硬件.初始化系统配置. 第二步: 启动系统数据库. 第三步: 准备好网 ...
- oracle表空间使用率统计查询
今天发现有一张采样表从1月5号开始不记录数据了,所以想查看一下表空间使用率,在网上零零散散找了很多资料,现在记录如下,也不知道哪一个最准确.还有一个就是网上拷贝的sql代码格式太乱了,不好看,找到一个 ...
- ASP.NET抓取网页内容的实现方法
这篇文章主要介绍了ASP.NET抓取网页内容的实现方法,涉及使用HttpWebRequest及WebResponse抓取网页内容的技巧,需要的朋友可以参考下 一.ASP.NET 使用HttpWebRe ...
- Oracle EBS-SQL (PO-17):检查供货比例不为100%.sql
select * from apps.MRP_SOURCING_RULES msrwhere organization_id=X. a ...
- QT:用QSet储存自定义结构体的问题——QSet和STL的set是有本质区别的,QSet是基于哈希算法的,要求提供自定义==和qHash函数
前几天要用QSet作为储存一个自定义的结构体(就像下面这个程序一样),结果死活不成功... 后来还跑到论坛上问人了,丢脸丢大了... 事先说明:以下这个例子是错误的 #include <QtCo ...
- 在类似qq或者微信聊天中。如何根据不同的手机发送图片
原文:在类似qq或者微信聊天中.如何根据不同的手机发送图片 前一段时间,公司自己要求做多客服开发,但是对于发送图片这一块,当时很苦恼,我用自己的手机(米2)测试,不管是本地,还是云相册,最新照片. ...
- Qt5 基于TCP传输的发送/接收文件服务器(支持多客户端)
一.实现功能 1.服务器端选择待发送的文件,可以是多个 2.开启服务器,支持多客户端接入,能够实时显示每个客户端接入状态 3.等待所有客户端都处于已连接状态时,依次发送文件集给每个客户端,显示每个客户 ...