在日常的开发过程中,std标准库中的容器std::vector和std::map以及Qt中容器QList和QMap使用频率非常高,但这些容器也有自己的使用技巧,如果使用不好,可能会出现bug。今天抽点时间,简要整理下。
容器使用前提:
定义结构体:
struct testStruct
{
std::string strId;
int nTest;
std::string strInfo;
};
std::string strFindId = "testId_3"; // 需要查找的字符串id
1.std::vector使用
首先对std::vector初始化;初始化如下(这里采用指针的方式存储):
std::vector中的结构体指针的strId都是唯一的,不存在重复的Id号。一下测试代码不适用结构体中相同的id号,否则查找结果就不对了。
std::vector<testStruct*> testStructList;
for (int i = 0; i < 10; i++)
{
testStruct* tsPtr = new testStruct;
tsPtr->strId = strId + std::to_string(i + 1);
tsPtr->nTest = i;
tsPtr->strInfo = "testStruct";
testStructList.push_back(tsPtr);
}
1):查找,这里提供了2中方法;
std::string strFindId = "find_";
方法1:使用迭代器
bool bFind = false;
for (auto it = testStructList.begin(); it != testStructList.end(); it++)
{
if ((*it)->strId.compare(strFindId) == 0)
{
// 这里可直接进行返回或者赋值
bFind = true;
}
}
方法2:使用c++ 11提供的方法
bFind = false;
auto itor = std::find_if(testStructList.begin(), testStructList.end(), [&strFindId](auto it) {
if (it->strId.compare(strFindId))
return true;
return false;
});
if (itor != testStructList.end())
{
// 这里可直接进行返回或者赋值
bFind = true;
}
2):删除某一项
方法1:使用迭代器
for (auto it = testStructList.begin(); it != testStructList.end();)
{
if (strFindId.compare((*it)->strId) == 0)
{
delete* it;
it = testStructList.erase(it);
}
else
++it;
}
方法2:使用c++11提供的方法
testStructList.erase(std::remove_if(testStructList.begin(), testStructList.end(), [strFindId](const testStruct* pItem) {
bool ret = (pItem->strId == strFindId);
if (ret)
{
delete pItem;
pItem = nullptr;
}
return ret;
}), testStructList.end());
3):清空
方法1:for循环
for (auto it = testStructList.begin(); it != testStructList.end();)
{
delete* it;
it = testStructList.erase(it); // 需要将it迭代器重新赋值
}
方法2:while循环
while (!testStructList.empty())
{
auto it = testStructList.back();
delete it;
testStructList.pop_back();
}
2.std::map使用
同样,先初始化std::map,初始化如下:
std::map<std::string, testStruct*> mapStruct;
for (int i = 0; i < 10; i++)
{
testStruct* tsPtr = new testStruct;
tsPtr->strId = strId + std::to_string(i + 1);
tsPtr->nTest = i;
tsPtr->strInfo = "testStruct";
mapStruct[tsPtr->strId] = tsPtr;
}
1.查找或删除,
方法1:采用find函数查找
bool bFind = false;
auto it = mapStruct.find(strFindId);
if (it != mapStruct.end())
{
// 查找,可直接赋值或者返回
bFind = true;
// 删除
delete it->second;
it->second = nullptr;
mapStruct.erase(it);
}
方法2:采用map的[] 操作符函数来实现
auto p = mapStruct[strFindId];
if(p)
{
delete p;
p = nullptr;
}
注意:采用map[]操作符函数,仅针对指针方式,如果是对象的方式,auto p中的p是一个未进行初始化的临时结构体对象。
2.清空
方法1:采用for循环
for (auto it = mapStruct.begin(); it != mapStruct.end();)
{
delete it->second;
it = mapStruct.erase(it);
}
方法2:采用while循环
while (!mapStruct.empty())
{
auto it = mapStruct.begin();
delete it->second;
it->second = nullptr;
mapStruct.erase(it);
}
3.QList使用
初始化的代码与std::vecotr基本一致,声明部分:
QList<testStruct*> testStructQtList;
for (int i = 0; i < 10; i++)
{
testStruct* tsPtr = new testStruct;
tsPtr->strId = strId + std::to_string(i + 1);
tsPtr->nTest = i;
tsPtr->strInfo = "testStruct";
testStructQtList.push_back(tsPtr);
}
1.查找与删除
foreach (auto item, testStructQtList)
{
if(strFindId.compare(item->strId) == 0)
{
//return ptdi;
testStructQtList.removeOne(item);
}
}
2.清空
qDeleteAll(testStructQtList);// 注意,该容器中存放的一定是指针,才能使用该函数
testStructQtList.clear();
4.QMap使用
初始化的代码与std::vecotr基本一致,声明部分:
QMap<testStruct*> mapStructQt;
for (int i = 0; i < 10; i++)
{
testStruct* tsPtr = new testStruct;
tsPtr->strId = strId + std::to_string(i + 1);
tsPtr->nTest = i;
tsPtr->strInfo = "testStruct";
mapStructQt[tsPtr->strId] = tsPtr;
}
1.查找与删除
与std::map使用类似
方法1:使用find函数
auto it = mapStructQt.find(strFindId);
if (it != mapStructQt.end())
{
delete it->second;
it->second = nullptr;
mapStructQt.erase(it);
}
方法2:直接使用[]操作符函数,注意事项与std::map一致,value值只能是指针
auto p = mapStructQt[strFindId];
if(p)
{
delete p;
p = nullptr;
}
2.清空,释放内存
qDeleteAll(mapStructQt);// 注意,该容器中存放的一定是指针,才能使用该函数
mapStructQt.clear();
以上就是常用容器的增删改查等功能,这些简单的功能,稍有不慎,就会出现bug,今天早上正好抽出点时间来整理下,写的比较仓促,如有bug可以与我联系,不胜感激。好了,今天就到这了