相同类型的对象总是成对出现。它们永远不会孤独,它们永远不会超过两个,就像纠缠的粒子一样。
我想用同一类的两个实例互相引用在C ++中实现此问题。创建主实例会自动创建辅助实例:
#include <iostream>
using namespace std;
class Particle
{
public:
// Constructs primary instance
Particle() :
partner_(Particle(*this))
{
cout << "Hi, I'm primary." << endl;
}
private:
// Constructs secondary instance
Particle(Particle & partner) :
partner_(partner)
{
cout << "Hi, I'm secondary." << endl;
}
Particle & partner_;
};
int main()
{
Particle two_friends;
return 0;
}
无法编译:
main.cpp: In constructor ‘Particle::Particle()’:
main.cpp:10:14: error: cannot bind non-const lvalue reference of type ‘Particle&’ to an rvalue of type ‘Particle’
partner_(Particle(*this))
^~~~~~~~~~~~~~~
是否可以使用引用来解决此问题?还是必须使用指针?
答案 0 :(得分:1)
您的系统中存在一个巨大的问题,第一个在堆栈上创建的粒子是实时的,但是第二个又如何呢?在您的代码中,它是作为temp变量创建的,并在构造函数中销毁了,因此在类内部进行引用是毫无用处的。我认为您应该做的是在另一个包装上使用std :: pair并自己设置伙伴,例如
struct ParticlePair{
Particle first;
Particle second;
ParticlePair()
{
first.setPartner( second );
second.setPartner( first );
}
}
最好将“粒子”构造函数设为私有,并将“粒子对”声明为朋友,在这种情况下,您将无法单独创建“粒子”。
如果您尝试使用指针,则还有另一个问题:如何正确删除?首先删除应先删除第二个,但这意味着第二个删除也应首先删除。迟早您将删除已删除的指针或删除在堆栈上创建的对象。
答案 1 :(得分:1)
之所以无法编译,是因为编译器使您免于犯错,并且不允许将临时对象传递给函数(或构造函数),因为这可能会导致错误。在您的情况下,您的临时对象将在构造函数的末尾被销毁,并且您只有一个粒子带有悬空引用,该引用指向现在已销毁的另一个对象。
一种解决方案是使用共享指针和弱指针(您需要弱指针或有循环引用)。
#include <memory>
class Particle
{
public:
static std::shared_ptr< Particle > create()
{
std::shared_ptr< Particle > first( new Particle() );
std::shared_ptr< Particle > second( new Particle() );
// first will own second
first->partner = second;
// second will have a weak pointer to first
second->weakPartner = first;
return first;
}
std::shared_ptr< Particle > getPartner()
{
if (partner)
{
return partner;
}
return weakPartner.lock();
}
private:
Particle() {};
std::shared_ptr< Particle > partner;
std::weak_ptr< Particle > weakPartner;
};
int main()
{
std::shared_ptr< Particle > two_friends = Particle::create();
}
对第一个粒子保持shared_ptr
可使第二个粒子保持活动状态,但请注意,如果对第二个粒子只有shared_ptr
,则第一个粒子将被销毁。您可以通过不使用weak_ptr
来避免这种情况,但是在破坏粒子之前,您必须手动中断shared_ptr
循环。