在Visual Studio 2010中我创建了一个while语句,在其中我指定了一个指向地图的指针。 例如:
std::map<int,std::tuple<int,std::string>** > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = &t;
dmap[i + 1 ] = &t;
i++;
}
.
.
.
for (auto it = d.begin();it!=d.end();++it)
{
if(*(it->second) != nullptr){
delete *(it->second);
*(it->second) = nullptr;
}
}
问题是&t
的地址始终相同,因此在最后,对于我输入的所有密钥,地图始终包含最后*t
值。
问题是什么? (解决)
[编辑] 现在我修改代码beacause它不完整之前,如果我想避免删除nullptr我需要有一个指针指针。或者不是?
答案 0 :(得分:3)
问题在于您将指向局部变量t
的指针放入地图中。在每个循环之后,t
被销毁并且指针不再有效。
我根本不知道你为什么要使用指针,更不用说指针了。您可能希望将元组本身放在地图中:
std::map<int,std::tuple<int,std::string>> dmap;
for (int i = 0; i<3; ++i){
dmap[i] = {10+i, "test"};
}
答案 1 :(得分:1)
我创建一个while语句,在其中我指定一个指向地图指针的指针
很抱歉这样说,但听起来我觉得你遇到的问题比t都相同(这看起来像xy problem)。
考虑(按顺序)其中一种选择:
按值存储您的元组
通过单个指针存储元组(比“按值”更差,优于“通过指针指向”)。如果您可以这样做,请考虑将地图声明为std::shared_ptr<std::tuple<...>>
)
如果你真的需要一个指向元组指针的指针映射,可以考虑创建一个最小的代理对象,它就像一个指向内部的指针的智能指针(并以安全的方式为你管理分配),并像常规一样从外面输入(并相应地重新声明你的地图)。
无论哪种方式,如果你真的需要一个指向元组指针的指针映射(由于某种原因),分配应该像这样完成:
std::map<int,std::tuple<int,std::string>**> dmap;
int i=0;
while (i<3) {
*dmap[ i ] = new std::tuple<int,std::string>{10 + i, "test"};
++i;
}
(你这样做的方法是将相同的本地(堆栈)变量的地址添加到地图中,这会在退出本地函数后导致未定义的行为。)
答案 2 :(得分:0)
嗯,t
的地址始终相同,因为它是存储在堆栈中的局部变量。每次进入该区块时,t
都会在同一位置分配(因为您在离开t
机构后正在销毁while
。
相反,您需要在堆上分配它(如果这真的是您想要做的)。
std::tuple<int,std::string>** t = new std::tuple<int,std::string>*();
*t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
我无法看到你想要完成的任务,但这将是一个更好的解决方案:
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
更好的方法是使用智能指针代替原始指针。
更好的方法是按值存储对象(根本没有指针)。
答案 3 :(得分:0)
您为什么对std::tuple<int,std::string>**
感兴趣?
std::tuple<int,std::string>*
不足够吗?
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}