You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

emplace_back插入元素是否始终处于容器原end()迭代器位置?

使用emplace_back()在容器尾部插入元素时,新元素是否始终位于插入前的end()位置?

当使用emplace_back()在容器尾部插入元素时,新元素是否始终保证位于容器插入前的::end()位置?

我在示例代码里,通过把插入前的end()迭代器传给新插入的entity对象,成功输出了“Hello World”,但我想知道这种行为对所有容器都有保证吗?

编辑补充:正如评论指出,std::vector这类容器插入后可能会重新分配内存,迭代器会失效,不符合这种情况。但我想知道,所有插入后能保留迭代器有效性的容器,是否都满足这个特性?

#include <cstdio>
#include <functional>
#include <list>

struct entity
{
    entity(std::function<void()> fn)
        :   fn_( fn )
    { }

    auto print()
    {
        printf("Hello World!");
    }

    auto operator()() -> void {
        fn_();
    }

    std::function<void()> fn_;
};

using list_t = std::list<entity>;
using iterator_t = list_t::iterator;

int main()
{
    list_t mylist;

    mylist.emplace_back([it = mylist.end()]{ it->print(); });

    for (auto& item : mylist) {
        item();
    }
}

结论

对于**插入后能保证迭代器有效性(包括原end()迭代器)**的容器,emplace_back()插入的新元素确实会占据插入前end()迭代器指向的位置,这种行为是C++标准明确保证的。

具体分析

  • 符合条件的容器:

    • std::list:链表的节点结构决定了插入操作只会修改节点指针,所有原有迭代器(包括end()哨兵迭代器)都保持有效。新插入的节点恰好位于原end()之前的位置,这也是示例能正常运行的原因。
    • std::deque:在尾部插入元素时,除非内部缓冲区需要扩展,否则所有原有迭代器(包括end())都有效,新元素会占据原end()指向的位置。
  • 标准规则:
    根据C++标准,支持emplace_back()且插入操作不导致迭代器失效的容器,emplace_back()会在容器末尾构造新元素。容器的end()迭代器定义为指向最后一个元素的下一个位置,因此插入前的end()位置就是新元素的目标位置。插入完成后,原end()迭代器(对于链表这类容器)会指向新元素的下一个节点(即原哨兵节点),而新元素的位置正是原end()之前的位置。

  • 需要规避的容器:

    • std::vector、std::string:插入时若触发内存扩容,所有原有迭代器都会失效;即使未扩容,原end()迭代器也会失效,使用原end()访问新元素属于未定义行为。

内容的提问来源于stack exchange,提问作者glades

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:50:11