1.vector.clear导致vector interator incompatible?
A:首先要明白导致vector iterator incompatible错误的常见原因?比如vector越界访问。
一个比较经典的例子是:
1 VectorType::iterator it = someVector.begin(); 2 for (; it != someVector.end();) 3 { 4 if (*it== value) 5 { 6 someVector.erase(it); 7 } 8 else 9 { 10 ++it; 11 } 12 }
代码中,在erase操作后,没有修改it就继续循环,在与end()比较时,断言出现。
这里的主要问题是,vector可以用任意方法实现erase,不保证在erase一个元素后,后续的元素一定被移动到这个iterator所引用的位置(地址)。当然,这在几乎所有STL的实现中,都是对的,这也就是以前用VC6编译后运行没有问题的原因。但如果这里用的不是vector,而是list或是map,运行到这里,程序会毫不犹豫的崩溃。
正确的做法是这样的:
STL里所有的容器类的erase实现都会返回一个iterator,这个iterator指向了“当前删除元素的后继元素,或是end()”
因此,在遍历容器的所有元素过程中通过erase删除一个元素后,将erase的返回值赋给迭代变量:
1 VectorType::iterator it = someVector.begin(); 2 for (; it != someVector.end();) 3 { 4 if (*it== value) 5 { 6 it = someVector.erase(it); 7 } 8 else 9 { 10 ++it; 11 } 12 }
VS的STL带有很多特性,也有BUG。比如下面:
B.我的代码中没有任何关于iterator的使用,只是作为动态数组使用,当vector.clear是报该错误。
被怀疑是VS的BUG。
使用下面的代码则没问题:
1 while(!vec.empty() ) 2 { 3 vec.pop_back(); 4 };
注:使用empty()来判断为空的效率比使用size高。
C.返回vecotr类型时,一般需要引用符&和const修饰。
常见错误代码:
1 // testVecotr.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <vector> 6 class foo{ 7 public: 8 9 const std::vector<int> getVec(){return myVec;} //other stuff omitted 10 11 private: 12 std::vector<int> myVec; 13 14 }; 15 int _tmain(int argc, _TCHAR* argv[]) 16 { 17 foo myFoo; 18 std::vector<int>::const_iterator i = myFoo.getVec().begin(); 19 while( i != myFoo.getVec().end()) 20 { 21 //do stuff 22 ++i; 23 } 24 return 0; 25 }
上述代码在22行会出现vector iterator incompatible的错误。
原因是getVec返回的是一个copy. So the iterators are incompatible.
修改方法是:
const std::vector<int> & getVec(){return myVec;}
另外的解决方法:当你确实想得到copy时,可以用下面的方法得到iterator.
1 const std::vector<int> myCopy = myFoo.getVec(); 2 std::vector<int>::const_iterator i = myCopy.begin(); 3 while(i != myCopy.end()) 4 { 5 //do stuff 6 ++i; 7 }
2.临时对象的问题
返回临时对象的引用或指针是c++中常犯的错误,而返回临时对象是会返回一份临时对象的拷贝。
比如以下代码:getVec返回的是一份vector的拷贝,代码是完全没有问题的。但如果返回的是std::vector<int> &则会出错。
1 #include<iostream> 2 #include<vector> 3 std::vector<int> getVec() 4 { 5 std::vector<int> ivec(3,1); 6 return ivec; 7 } 8 int main(void) 9 { 10 std::vector<int> vecTest=getVec(); 11 std::cout<<vecTest.size()<<std::endl; 12 return 0; 13 }
有一篇文章分析了参数临时对象、类型转换和返回对象等三种临时对象的情况。
http://blog.csdn.net/microzone/article/details/6740475
3.当前目录的表示方法
当前目录的表示方法为:..\\input.txt
EnergyAverage("..\\Data\\b_0_core_1.txt");
4.C++将string字符串转化为整数等
首先用string类型的c_str方法转化为const char*,然后用atoi。
在此也要注意string的其他不常用方法:
string::assign()
string::data()
string::cory()
5.Segmentation fault in Linux
SIGSEGV在很多时候是由于指针越界引起的,但并不是所有的指针越界都会引发SIGSEGV。一个越界的指针,如果不解引用它,是不会引起SIGSEGV的。
链接:http://www.cnblogs.com/no7dw/archive/2013/02/20/2918372.html
http://www.cnblogs.com/justacoder/archive/2010/04/14/segmentation_fault.html
6. 注意区别 strlen和sizeof的区别
sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组、指针、类型、对象、函数等。
它的功能是:获得保证能容纳实现所建立的最大对象的字节大小。
strlen(...)是函数,要在运行时才能计算。参数必须是字符型指针(char*)。当数组名作为参数传入时,实际上数组就退化成指针了。
它的功能是:返回字符串的长度。该字符串可能是自己定义的,也可能是内存中随机的,该函数实际完成的功能是从代表该字符串的第一个地址开始遍历,直到遇到结束符NULL。返回的长度大小不包括NULL。
eg1、char arr[10] = "What?"; int len_one = strlen(arr); int len_two = sizeof(arr); cout << len_one << " and " << len_two << endl; 输出结果为:5 and 10 点评:sizeof返回定义arr数组时,编译器为其分配的数组空间大小,不关心里面存了多少数据。strlen只关心存储的数据内容,不关心空间的大小和类型。 eg2、char * parr = new char[10]; int len_one = strlen(parr); int len_two = sizeof(parr); int len_three = sizeof(*parr); cout << len_one << " and " << len_two << " and " << len_three << endl; 输出结果:23 and 4 and 1
详解:http://3961409.blog.51cto.com/3951409/766017
7. new创建类对象与不new区别(http://blog.163.com/zhuandi_h/blog/static/18027028820129169538815/)