C++11积累

reinterpret_cast

译自stackoverflow

reinterpret_cast能做的是允许你以不同于输入的方式读取内存,你给了它一个内存地址然后让它按照你的要求去读这部分内存。这就是为什么它只能用于指针和引用。让我们以下面的代码为例:

1
2
3
float a = 12;
int b = *reinterpret_cast<int*>(&a);
std::cout<<b;

第二行代码解析:

  1. 取a的地址
  2. reinterpret_cast为一个int*
  3. 得到一个指向a的int*
  4. 重新将指针返回的值作为int声明

如果运行这行代码我将得到输出1094713344,原因是12作为一个float型,在IEEE标准下的二进制表示为0100 0001 0100 0000 0000 0000 0000 0000,现在将这个二进制按照unsigned int读取,你将得到1094713344

这就是伪码reinterpret_cast被认为是很危险的,你只能当你有一个指针并且知道内存可以以你想要的方式读取的时候才能使用它。

erase的陷阱

vector

删除vector元素有两个函数原型

1
2
iterator erase (const_iterator position);
iterator erase (const_iterator first, const_iterator last);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <vector>
using namespace std;
int main()
{

vector<int> vec;
for(int i =0 ;i<10;i++)
vec.push_back(i);
vector<int>::iterator it1 = vec.begin();
vector<int>::iterator it2 = vec.end();
for(;it1!=it2;it1++)
if(*it1==2)
vec.erase(it1);
for(int i = 0;i<vec.size();i++)
cout<<vec[i]<<endl;
system("pause");
}

在Debug下运行会报错:vector iterator not incrementable! 就是说不不允许对一个已经被删除了的指针继续迭代,但是在Release下却可以正常运行且能达到从vec中删除元素2的目的,如果改成下面的代码在迭代中输出,那么输出的结果是0 1 3 4 5 6 7 8 9 9,因为vec在erase操作后默认将it1指向后一个元素,两个9应该是删除后前移并没有清除后面的元素,而it2又刚好在原来的迭代器末端。

1
2
3
4
5
6
for(;it1!=it2;it1++)
{
if(*it1==2)
vec.erase(it1);
cout<<*it1<<endl;
}

map

删除map中的元素有三个函数原型

1
2
3
iterator  erase (const_iterator position);
size_type erase (const key_type& k);
iterator erase (const_iterator first, const_iterator last);

在迭代过程中调用第一个erase函数的正确做法

1
2
3
4
5
6
7
typedef std::map<int, int>           KG_TestMap;
typedef std::map<int, int>::iterator KG_TestMapIter;
std::map<int, int> mapTest;
for (KG_TestMapIter iter = mapTest.begin(); iter != mapTest.end();)
{
mapTest.erase(iter++);
}
Thanks!