移植Java代码到C++的技巧(整合)
作者:网络转载 发布时间:[ 2013/4/17 9:53:25 ] 推荐标签:
2、在Java中,TreeMap的参数类型必须为对象类型,不能为原始数据类型,如int、double等,否则编译器将报编译错误。而在C++中,对模参的类型则没有此类限制。如果当Java源代码中TreeMap的值参数类型为自定义对象时,那么在C++中与其对应的值模参类型很有可能为该自定义对象的指针类型,否则将只能是该对象类型本身,这样在插入对象时,会有对象copy的动作发生,从而对性能造成一定的负面影响,通常而言,我们会选择使用该类的指针类型作为该容器的值模参类型。见如下Java代码:
public class MyTest {
private int _value;
public MyTest(int value) {
_value = value;
}
public static void main(String[] args) {
TreeMap<Integer,MyTest> tm = new TreeMap<Integer,MyTest>();
tm.put(5, new MyTest(10));
System.out.println("The count of the TreeMap is " + tm.size());
Set<Entry<Integer,MyTest>> entries = tm.entrySet();
Iterator<Entry<Integer,MyTest>> it = entries.iterator();
while (it.hasNext()) {
Entry<Integer,MyTest> e = it.next();
System.out.printf("key = %d, value = %d
",e.getKey().intValue(),e.getValue()._value);
}
}
}
//The count of the TreeMap is 1
//key = 5, value = 10
以上为Java的完整代码和输出结果。如果我们仍然用该种方式完成C++的代码实现,这样正确吗?答案是输出结果是一致的,但是在C++代码中却存在着一个极为低级的失误。对,内存泄露。见如下C++代码及代码注释:
using namespace std;
class MyTest
{
public:
MyTest(int value) {
_value = value;
}
~MyTest() {}
public:
int getValue() const {
return _value;
}
private:
int _value;
};
int main()
{
map<int,MyTest*> m;
m.insert(make_pair(5,new MyTest(10)));
map<int,MyTest*>::iterator it = m.find(5);
printf("The count of the map is %d.
",m.size());
it = m.begin();
for (; it != m.end(); ++it)
printf("key = %d, value = %d
",(*it).first,(*it).second->getValue());
return 0;
}
//The count of the map is 1
//key = 5, value = 10
在执行以上代码之后,如果借助于Valgrind(Linux gcc)或BoundChecker(Visual C++)等内存检测工具,便可以清楚的看到插入的MyTest对象指针在程序退出之前没有被正常释放,从而导致了内存泄露。见如下修订后的C++代码:
//该宏是我在实际项目中经常用到的工具宏之一
#define RELEASE_MAP(Type1,Type2,variable)
do {
map<Type1,Type2*>::iterator it = (variable).begin();
for (; it != (variable).end(); ++it)
delete (it->second);
(variable).clear();
} while(0)
int main()
{
map<int,MyTest*> m;
m.insert(make_pair(5,new MyTest(10)));
map<int,MyTest*>::iterator it = m.find(5);
printf("The count of the map is %d.
",m.size());
it = m.begin();
for (; it != m.end(); ++it)
printf("key = %d, value = %d
",(*it).first,(*it).second->getValue());
RELEASE_MAP(int,MyTest,m);
return 0;
}
修订后代码的输出结果与之前的代码是完全相同的,只是容器中对象指针的内存泄露问题此得以解决。然而这种类似的内存资源管理问题给你带来的困扰,将会在整个代码移植的过程中贯穿始末。有的时候我甚至直接忽略了内存资源泄露问题,并将C++的代码写的和Java中的源码完全一致,直到某一时刻才突然惊醒的发现,之后是不得不沮丧的进行重构,按照C++的机制和习惯方式重新实现该部分逻辑。
这里我们将不再此类问题做过多的赘述和解释,后面会有一个单独的条目来演示和分析该类问题。

sales@spasvo.com