正如@Vlad 所说,引用的问题是您将需要一个最终对象。好消息是,原则上,你仍然可以拥有一个循环列表,如果你有它的用处。这是一个基本的事情,如果“下一个”元素是不可为空的引用,则意味着总是有下一个元素,也就是说,列表要么是无限的,要么更现实地说,它会自行关闭或关闭到另一个列表中。
进一步练习是相当有趣和奇怪的。基本上,似乎唯一可能的事情是定义 a 节点的等价物(它也代表列表)。
template<class T>
struct node{
T value; // mutable?
node const& next;
struct circulator{
node const* impl_;
circulator& circulate(){impl_ = &(impl_->next); return *this;}
T const& operator*() const{return impl_->value;}
friend bool operator==(circulator const& c1, circulator const& c2){return c1.impl_ == c2.impl_;}
friend bool operator!=(circulator const& c1, circulator const& c2){return not(c1==c2);}
};
circulator some() const{return circulator{this};}
};
元素必须存在于堆栈中并且列表是静态的(好吧,无论如何引用都不能重新绑定)并且链接必须是const
引用!最终,显然value
可以制造mutable
(可能安全吗?)。(此时人们想知道这与模索引的堆栈数组引用有何不同。)
构造 /list 对象的方法只有一种node
,即用它自己(或用其他预先存在的节点)关闭它。所以结果列表要么是圆形的,要么是“rho”形状的。
node<int> n1{5, {6, {7, n1}}};
auto c = n1.some();
cout << "size " << sizeof(node<int>) << '\n';
do{
cout << *c << ", ";
c.circulate();
}while(c != n1.some()); //prints 5, 6, 7
我无法制作一个不易构造的节点(聚合?)。(添加任何类型的基本构造函数都会产生分段错误,原因我无法理解,在gcc
和中都是如此clang
)。出于同样奇怪的原因,我无法将节点封装在“容器”对象中。所以制作一个可以像这样构造的对象对我来说是不可能的:
circular_list<int> l{1,2,3,4}; // couldn't do this for obscure reasons
最后,由于无法构造适当的容器,因此不清楚该对象的语义是什么,例如当两个“列表”相等时?什么不意味着分配?或在不同大小的列表之间分配?
这是一个非常矛盾的对象,显然没有普遍的价值或引用语义。
欢迎任何意见或改进!