我有一个指向矢量的指针:
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
vector<double>* new_mv_pt = new vector<double> (3);
new_mv_pt = &mv;
cout << (*new_mv_pt)[1] << endl;
如何创建另一个将此指针存储到向量的向量? 我正在尝试这个...
vector<double*> vop = new vector<double> (3);
vop.push_back(*new_mv_pt);
cout << (*vop)[1] << endl;
但它不起作用。我正在尝试甚至可能吗?:
答案 0 :(得分:7)
哇,慢下来!
你在记忆中做了一些非常疯狂的事情,所以让我们从头开始。
您有一个包含3个元素的向量。您想使用指针引用该向量。让我们看看它的外观:
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// No no no no! You don't have to `new` a pointer that
// you're going to assign to something else!
// This is called a memory leak, and it means you've just wasted (!!!)
// C++ memory! Don't do it
// vector<double>* new_mv_pt = new vector<double> (3);
// Instead, do this:
vector<double>* ptr_to_mv = &mv; // No leak, immediately points to a vector<double> mv;
照顾第一位。现在,让我们更深入地了解它。您想要存储向量的引用向量。好吧,这听起来很公平。有几种方法可以解决它。让我们回到mv
和其他事情的例子:
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
vector<double>* ptr_to_mv = &mv;
// So far so good. Now, based on your question, you want
// to have a list of these to point to. So:
vector<vector<double>*> vop;
vop.push_back( ptr_to_mv ); // All clean.
在您的代码中,您必须使用vop
或.at()
访问operator[]
才能访问vector<double>*
,然后使用{{1}取消引用它或者使用*
直接处理它:
->
这会打印233,因为所有这些都是您引用std::vector<double>* ptr_to_vector = vop[0]; // Got my pointer
std::cout << ptr_to_vector->at( 0 ) << std::endl; // Prints '233'
的。在另一个答案的评论中,你说当你删除这些指针时,你会得到一个断言。 这应该发生,因为你要删除两次东西!
还记得mv
,你很久以前宣称过的吗?好吧,你没有把它变成一个动态矢量。你没有mv
它,它不是指针。因此,当函数退出时,它将自动删除自身 - 它将调用其析构函数并且 在堆栈中死亡 。如果你看new
或ptr_to_vector
,它们都会引用ptr_to_mv
来清理自己。
如果您对其进行了删除操作,那么您正试图在mv
上调用删除(这就是您所指向的内容)并且您正在进行双重删除! 强>
所以,当你有一个指向mv
的指针时,不要删除它。这是一个基于堆栈的变量。它会清理自己。
仍然关注?好的,让我们进一步了解一下:
现在,如果有一个原因你需要mv
向上一个向量,你不要用旧指针指定覆盖它(正如我之前告诉你的那样,你会离开记忆)。你创造了一个全新的指针:
new
上面显示了问题:我们有2个指针,都在// Our vector of double vector pointers
vector<vector<double>*> vop;
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// References a stack variable: don't delete
vector<double>* ptr_to_mv = &mv;
vop.push_back( ptr_to_mv );
// Makes a fresh copy of mv. You must delete this
// manually
vector<double>* fresh_ptr = new vector<double>( mv );
(*fresh_ptr)[0] = 1337;
// changes only data in fresh_ptr, not `mv`
vop.push_back( fresh_ptr );
/* Blah blah blah, work */
// Functions about to exit, gotta clean up!
delete fresh_ptr;
//delete ptr_to_mv; // NO.
//delete vop[0]; // NO!
//delete vop[1]; // ... Already deleted from fresh_ptr
// ... This is going to get tedious if we don't have a fresh_ptr
// for every vector we need!
内,其中一个需要通过调用delete来清理,而另一个则不需要,因为它只是对vop
的引用,自动清洁!循环向量并删除所有内容将导致令人讨厌的断言发生。我们如何处理它并仍然得到我们需要的清理?
肮脏和快速解决方案1只是mv
/ delete vop[1]
并完成它。更好的解决方案是,无论何时fresh_ptr
资源,你都可以将它包装在一个名为std::unique_ptr
的奇妙事物中。代码如下所示:
new
然后你去,删除所有注释掉的代码,突然间,你的东西就像吹口哨一样干净!
当然,现在,我的最后一个问题是: 你到底在做什么,需要所有这些指针指向矢量指针的引用?
答案 1 :(得分:3)
是的,但你需要这样做:
vector<vector<double>*> vop;
因为您正在寻找矢量指针列表。
你在这里有什么:
vector<double *> vop
只是double
指针的向量。
你也只想要这个:
vop.push_back(new_mv_pt); // <- No asterisk (you don't want to de-reference it)
答案 2 :(得分:2)
这里有内存泄漏:
vector<double>* new_mv_pt = new vector<double> (3);
new_mv_pt = &mv;
您正在堆上创建vector<double>
,将其地址存储在new_mv_pt
中,然后覆盖该地址的地址为mv
。 vector<double>
仍然存在于堆上,但您已永久丢失其地址(因此无法delete
或使用它执行任何其他操作。)
此代码:
vector<double*> vop = new vector<double> (3);
vop.push_back(*new_mv_pt);
cout << (*vop)[1] << endl;
不起作用,因为vop
是double*
的向量,并且您正尝试在其中插入vector<double>
。有关正确的方法,请参阅Ben's answer。