【发布时间】:2020-09-04 16:12:11
【问题描述】:
我正在尝试创建一个连通图并对其执行某些计算。为此,我需要从该图中的每个节点访问其邻居,并从其邻居访问其邻居的邻居,依此类推。这不可避免地会产生许多(有用的)循环依赖。
下面是一个简化示例,其中包含 3 个相互连接的节点(例如三角形的 3 个顶点),我不确定这种方法是否是一种好方法,特别是如果清理留下任何内存泄漏:
#include <iostream>
#include <vector>
class A {
public:
int id;
std::vector<A*> partners;
A(const int &i) : id(i) {
std::cout << id << " created\n";
}
~A() {
std::cout << id << " destroyed\n";
}
};
bool partnerUp(A *a1, A *a2) {
if (!a1 || !a2)
return false;
a1->partners.push_back(a2);
a2->partners.push_back(a1);
std::cout << a1->id << " is now partnered with " << a2->id << "\n";
return true;
}
int main() {
std::vector<A*> vecA;
vecA.push_back(new A(10));
vecA.push_back(new A(20));
vecA.push_back(new A(30));
partnerUp(vecA[0], vecA[1]);
partnerUp(vecA[0], vecA[2]);
partnerUp(vecA[1], vecA[2]);
for (auto& a : vecA) {
delete a;
a = nullptr;
}
vecA.clear();
return 0;
}
我也知道我可以使用 shared_ptr + weak_ptr 来完成任务,但是智能指针会带来开销,我希望尽可能避免这种情况(我也讨厌使用 .lock( )一直访问数据,但这并不重要)。我使用智能指针重写代码如下,我想知道两段代码之间有什么区别(两段代码的输出相同)。
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class A {
public:
int id;
vector<weak_ptr<A>> partners;
A(const int &i) : id(i) {
cout << id << " created\n";
}
~A() {
cout << id << " destroyed\n";
}
};
bool partnerUp(shared_ptr<A> a1, shared_ptr<A> a2) {
if (!a1 || !a2)
return false;
a1->partners.push_back(a2);
a2->partners.push_back(a1);
cout << a1->id << " is now partnered with " << a2->id << "\n";
return true;
}
int main() {
vector<shared_ptr<A>> vecA;
vecA.push_back(make_shared<A>(10));
vecA.push_back(make_shared<A>(20));
vecA.push_back(make_shared<A>(30));
partnerUp(vecA[0], vecA[1]);
partnerUp(vecA[0], vecA[2]);
partnerUp(vecA[1], vecA[2]);
return 0;
}
【问题讨论】:
-
“我想知道这两段代码有什么区别” 嗯,我不太明白你在找什么样的答案.
-
使用
vector<unique_ptr<A>>或deque<A>也很好(在main中)。通常,人们想避开这个容器,只在图中存储指针。然后,删除就成了问题。 -
第二个带有智能指针的代码应该没有泄漏,我想知道第一个代码是否也是如此。如果两个代码都没有泄漏,我更喜欢使用第一个。
-
但是通过在 main() 中使用 vector
> 我将无法执行 partnerUp 并且所有连接都丢失了 -
But by using vector<unique_ptr<A>> in main() I wouldn't be able to do partnerUp and all connections are lost这不是真的。智能指针和原始指针的组合是一种有效的方法。如果你有一个树结构,一个节点唯一地保存它的子节点并引用它的父节点,对子节点使用unique_ptr,对父节点使用原始指针就可以了。对于复杂图,图本身将拥有节点并管理它们的连接,并且节点已经连接,在这里您也可以使用unqiue_ptr和原始指针。
标签: c++ smart-pointers cyclic-dependency raw-pointer