在快放假的前两三个星期,移植公司一个大神负责的项目的代码,我第一次接触这种一个函数就有一千多行的代码,有点大开眼界啊同时忙到飞起!大神就是不一样!他本来在windows下写的是C风格的,然后我先将这些直接放在一个类里测试了一遍,然后将其转成C++风格的,最后再在linux上调试测试对比。
这次的移植让我明白了一个问题,原来移植不只是复制粘贴,那么就不叫做移植了。然后就是找问题找bug是一个漫长的调试过程,还有就是有时候通过调试知道了是在某一行出现了问题,但真正导致出问题的不是这一行,或者不是这一行附近的一些行,因为这些行逻辑和语法上都没有任何问题。真正的问题出现在之前不报错的某一行或者某些行中,经过一定时间导致了内存泄漏,感觉内存泄露真的是个不好找的问题。
我出现的一些问题,总结如下,怕以后自己忘记:
1、vector.clear()之后导致的下标超出问题(特别是在循环判断中)
比如在一个vector的循环中有一个判断,满足这个判断就clear这个容器,那么下一次再循环时,容器里面什么都没有,所以不能访问容器某个位置的元素了,这样会报下标超出的错。
2、vector.erase()导致的迭代器失效问题
erase语句会返回一个迭代器,比如现在对第三个位置的元素进行erase,那么内部是第四个位置的元素自动填补上来,会移到第三个位置处,所以返回的仍然是第三个位置处的迭代器,但这个迭代器指的元素已经是下一个元素了而已。
我本来是这样子修改的:
for(vector<int>::iterator it=vec.begin();it!=vec.end();it++){这样子没有语法错误,但它漏掉了元素,因为erase返回的本来就是下一个元素了,还进行it++就是下下个元素了,所以漏掉了一些元素,没有达到遍历所有元素的效果。后来我修改成新定义一个迭代器:vector<int>::iterator iter=vec.erase(it);然后不用这个迭代器,当然it++也会跳过 但我后面想办法不让它跳过,总之也搞定了。但这样子老板不放心。
if(*it==0){
it=vec.erase(it);
if(it==vec.end())
break;
else
continue;
}
......
}
最后老板说将所有满足if的需要删掉的元素的位置用一个数组保存起来,在循环结束后,对vector里的每个元素进行遍历,如果这个元素的下标不是之前的数组里的,那么就保存这个元素到另一个新容器中,否则不保存这个元素,对下一个元素下标进行判断。老板说这样最安全。
3、memset不能给类清零,最好只给数组或结构体清零
本来是一个包含string和int的结构体,结果我用memset对这个结构体进行清零,后来报错了。原来不能对类、包含类的数组或结构体进行清零。因为类有自己的一套方式。
4、linux函数声明和定义时的默认实参与windows上的有点不一样
如果我没记错,windows上函数声明和定义时都可以写上默认实参的值,但linux上却是在声明时写了默认实参的值在定义时就不能写了。
5、windows转成linux时同样的代码不能跑是格式问题
在windows和linux之间进行转换,好像有格式问题,自动的。可以用记事本查看格式被转成了什么格式,转到适合各自系统的再保存一遍就可以了。
6、windows下sort()函数自定义比较规则时
sort( ,,)如果第三个参数是个返回bool型的函数f(),如果这个函数是个全局的函数,那么直接用它的名字做第三个参数就是了,就代表指向函数地址的指针;如果这个函数是某个类的成员函数,那么一定要加类作用域限定符,不然找不到的。
//sort(AlgaePriority.begin(), AlgaePriority.end(), &EcologyMath::SortForVectorByPriority|);//windows:类名::函数名
7、linux和windows下使用三个实参的sort()函数调用形式不一样的问题
windows下调用三个参数的sort()函数就是第三个参数直接用函数名即可;但linux下不是 :
sort(AlgaePriority.begin(), AlgaePriority.end(), bind(&EcologyMath::SortForVectorByPriority,this,_1,_2));//linux
//sort(AlgaePriority.begin(), AlgaePriority.end(), &EcologyMath::SortForVectorByPriority|);//windows
8、又犯了个傻问题 声明几个同类型指针时我竟然并排声明
IplImage* img1;
IplImage* img2;
应该这样才对嘛。
9、Alt加左箭头表明回退 Ctrl加Z也表示回退 但两种回退有点不同 Ctrl加/表明注释 cvSobel()在转化为Sobel()时的问题还要加句
10、还有别的我写的傻问题 比如new了没delete啊 boundingRect函数的问题 while里我本来还写了个死循环 还有C风格的寻找凸包和凹陷检测时最远点转化为C++风格时的问题。
11、opencv3.1和opencv3.2加载SVM分类器的函数放的位置不一样了
//opencv3.1
Ptr<ml::SVM> fusizao_svm;
fusizao_svm = ml::SVM::create();
fusizao_svm = ml::SVM::load<ml::SVM>("fusizao_svm.xml");
//opencv3.2
Ptr<cv::ml::SVM> fusizao_svm;
fusizao_svm = ml::SVM::create();
fusizao_svm = Algorithm::load<cv::ml::SVM>("fusizao_svm.xml");
还有opencv3.2里创建一个n行m列的新Mat时,我试了各种创建形式,可总是说我没有匹配,明明我是匹配那个Mat的构造函数的,为什么呢???
后来我实在不知道原因 没办法就用cvCreateImage创建了一个IplImage* 然后将其用cvarrToMat()创建了一个新Mat。
还有个错误就是:error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options. 按照网上的没有解决 ,后来请教同事 原来在工程的Setteing中 在GCC C++ compiler和GCC C compiler的Command中 添加 :gcc -std=gnu++11即可。
还有个问题 就是opencv3.2没有CvMLData了 不能用read_csv来加载csv文件了 谷歌到新办法:http://answers.opencv.org/question/73223/cant-create-csv-file/
还有个问题 windows上没有报错 但到linux会报错 比如:
struct myPoint {在linux上会报错说: 将'const xxx'作为'xxx'的'this'实参时丢弃了类型限定。 百度后找到:http://blog.csdn.net/snail_running/article/details/50705437 我改成:
int x;
int y;
bool operator<(const myPoint &pt) {
if (x == pt.x)
{
return (y < pt.y);
}
return (x < pt.x);
}
};
struct myPoint {
int x;
int y;
bool operator<(const myPoint &pt)const { //this func is different from the one on windows!!!!
if (x == pt.x)
{
return (y < pt.y);
}
return (x < pt.x);
}
};
这样就行了。
12、Opencv3.2中原来创建Mat时不可以是(size,depth,channels)了 但(size,type)等方式还是可以的 另外Mat::channels() 以前的channels只是成员变量 现在变成了成员函数了。
13、关于类的成员函数的形参是这个类的另一个成员函数的问题:
class tempclass{原来是这样用的。
public:
string son_func1(int,char){...}
string son_func2(int,char){...}
typedef string(tempclass::*classify)(int,char);
void father_fun(float tea,bool teb,classify func){
int tempa=5;
char tempb='a';
string temp=(this->*func)(tempa,tempb);
...
}
bool last_fun(bool,int,double){
classify addr=&tempclass::son_func1;
//或者 :classify addr=&tempclass::son_func2;
float reala=4.56;
father_fun(reala,true,addr);
...
}
private:
...
};
还有个小问题但困扰了我好久的 在linux上我申请一个大数组:uchar* arrname=new uchar(256*256*256);这样竟然不行,原来要这样:
uchar* arrname=new uchar[256*256*256];
http://pan.baidu.com/s/1hsJruYC