C++ 为什么不是';t std::list::拼接自由函数?

C++ 为什么不是';t std::list::拼接自由函数?,c++,doubly-linked-list,C++,Doubly Linked List,Splice是一个成员函数,它在固定时间内将链表的一部分放入另一个链表中 为什么它需要是一个成员函数?我希望我可以只使用迭代器拼接到列表中,并且在列表本身上有一个句柄。除了起始迭代器和结束迭代器之外,为什么要拼接的列表还需要是一个参数 为了进行测试,我列出了三个列表,并混合了容器和迭代器。 请参见下面的拼接图,其中容器(空)与迭代器(test0和test1)不匹配: 我可以理解迭代的工作原理,因为它只运行到next为null,而不考虑容器的前/后指针。但是它是如何得到正确的尺寸的呢?也许大小是动

Splice是一个成员函数,它在固定时间内将链表的一部分放入另一个链表中

为什么它需要是一个成员函数?我希望我可以只使用迭代器拼接到列表中,并且在列表本身上有一个句柄。除了起始迭代器和结束迭代器之外,为什么要拼接的列表还需要是一个参数

为了进行测试,我列出了三个列表,并混合了容器和迭代器。 请参见下面的拼接图,其中容器(空)与迭代器(test0和test1)不匹配:

我可以理解迭代的工作原理,因为它只运行到next为null,而不考虑容器的前/后指针。但是它是如何得到正确的尺寸的呢?也许大小是动态计算的

编辑:根据大小的大小,以线性时间动态计算列表的大小。所以容器实际上只是一个伪参数。可能只有在添加新元素时才需要它,因为它具有用于在列表中创建新节点的分配器?

修改容器的大小。不能使用容器的迭代器修改容器的大小。您会注意到,标准库中没有可以仅使用迭代器将新元素插入范围的自由函数。充其量他们可以重新安排

例如,在容器末尾洗牌要删除的元素,并返回一个迭代器,标识需要删除的元素范围。它不能真正从范围本身移除元素


有一些变通方法,例如通过使用,但通过模拟未绑定的范围来实现。

前几天我正在研究std::list::splice实现。 通常,迭代器抽象指向列表节点私有实现的指针。列表节点包含指向其相邻节点的_M_prev和_M_next指针-这完全取决于实现。对于空列表,该列表包含一个sentinal节点,它同时充当头部和尾部(同样取决于实现)

所以我想我会尝试只使用列表节点来实现拼接:

void splice(const_iterator pos, list& other,
            const_iterator first, const_iterator last)
{
    // Hook up last.
    last->_M_next = pos->_M_next;
    pos->_M_next->_M_prev = last;

    // Hook up first.
    pos->_M_next = first;
    first->_M_prev = pos;
}
我认为这看起来是正确的,但我可能错了

因此,基于该实现,如果大小是动态计算的,那么这将如您所说的那样工作


然而,正如François Andrieux所指出的,动态计算大小是浪费的,因此需要涉及容器,以便维护内部大小计数。

您的意思是
std::list::splice
?标准库没有
std::splice::insert
。值得一提的是,在C++11之前,从技术上讲,splice可以作为一个免费函数使用:
list::size
是O(n),因此不必缓存大小(并确保它是正确的)在列表本身内部。@Revolver\u Ocelot我认为问题在于,这样一个函数将需要一个全新的迭代器类别,它是链表迭代器所独有的。现有迭代器类别不具备重新链接列表中元素所需的接口。虽然我同意这似乎是可能的。@Eyal那只是未定义的行为。未定义行为的一个常见且不幸的结果似乎给出了预期的结果。但是这种行为在任何时候都可能因任何原因而改变。@Eyal“它看起来很有效”是执行无效代码最危险的结果。顺便说一句,我还有其他结果,请确保您至少使用了C++11:@Eyal From cppreference:
first
last
-要从
其他
传输到
*此
的元素范围。根据实际标准:
void splice(常量迭代器位置,列表&x,常量迭代器第一,常量迭代器最后) 11:<代码> [第一,最后] <代码>是 x中的有效范围。它不是浪费,它是非法的,根据C++标准:所有<代码>。大小< /代码>函数是C++(11)以来的O(1)。在此之前,列表<代码>大小<代码>为O(n)。实现这样的功能确实是可能的。但是,你已经晚了7年。
empty size: 0
test0 size: 6
test1 size: 0
1
2
3
4
5
6
void splice(const_iterator pos, list& other,
            const_iterator first, const_iterator last)
{
    // Hook up last.
    last->_M_next = pos->_M_next;
    pos->_M_next->_M_prev = last;

    // Hook up first.
    pos->_M_next = first;
    first->_M_prev = pos;
}