哇,慢点!
你正在用你的记忆做一些非常疯狂的事情,所以让我们从头开始吧。
您有一个包含 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
with.at()
或才能访问operator[]
a vector<double>*
,然后使用取消引用它*
或->
直接使用它来处理它:
std::vector<double>* ptr_to_vector = vop[0]; // Got my pointer
std::cout << ptr_to_vector->at( 0 ) << std::endl; // Prints '233'
这将打印 233 因为所有这些都是您引用的mv
。在另一个答案的评论中,您说当您删除这些指针时,您会得到一个断言。这应该会发生,因为您要删除两次!
还记得mv
,你很久以前就宣布过吗?好吧,你没有让它成为一个动态向量。你没有new
,它不是指针。所以当函数退出时,它会自动删除自己——它会调用它的析构函数并死在堆栈上。如果您查看ptr_to_vector
or ptr_to_mv
,它们都在引用mv
,它会自行清理。
如果您对其调用 delete ,则您正在尝试调用 delete mv
(这就是您所指向的)并且您正在双重删除!
所以,当你有一个指向 的指针时mv
,不要删除它。它是一个基于堆栈的变量。它会自己清理。
还在追?太好了,让我们再深入一点:
现在,如果出于某种原因需要添加new
向量,则不要用旧指针指定覆盖它(正如我之前告诉过的,你会留下内存)。您制作了一个全新的指针:
// 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!
上面显示了问题:我们有两个指针,都在里面vop
,一个需要通过调用 delete 来清理,另一个不需要,因为它只是对 的引用mv
,它会自动清理!循环遍历向量并删除所有内容将导致该讨厌的断言发生。我们如何处理它并且仍然得到我们需要的清理?
肮脏而快速的解决方案 1 就是delete vop[1]
/fresh_ptr
并完成它。更好的解决方案是,每当你new
获得一个资源时,你将它包装在一个叫做std::unique_ptr
. 代码将如下所示:
// Our vector of double vector pointers. Non-owning
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
// puts it inside a std::unique_ptr,
// which, like a stack-based vector,
// can clean itself up
std::unique_ptr<vector<double>> fresh_ptr( new vector<double>( mv ) );
vop.push_back( fresh_ptr.get() );
/* Blah blah blah, work */
// Functions about to exit, gotta clean up!
//delete fresh_ptr; // Not necessary
//delete ptr_to_mv; // Nope.jpg
你去那里,删除所有注释掉的代码,突然间,你的东西就像口哨一样干净!
当然,现在,我要问你的最后一个问题是:
你到底在做什么,需要所有这些指向向量指针引用的指针?