c++ 由emplace_back插入的元素是否总是选择::end()迭代器?

5ktev3wc  于 2023-01-06  发布在  其他
关注(0)|答案(2)|浏览(139)

如果我在一个容器的后面插入一个元素(例如emplace_back()),新元素是否总是保证在前面的::end()位置?
比较以下示例:在这里,这是有效的,因为我可以将迭代器传递给新插入的实体对象,该对象又依赖于它来向控制台输出“Hello World”。我想知道这是否保证对每个容器都有效。

EDIT:正如注解中所指出的,由于插入后的重分配,std::vector和consort已经退出。但我仍然想知道是否所有containers在插入后都是迭代器保留的。

演示

#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();
    }
}
afdcj2ne

afdcj2ne1#

在你所显示的代码中,lambda将在lambda被示例化时捕获结束迭代器。由于结束迭代器没有指向一个有效的节点,所以你不允许取消引用它。重要的是要理解,你的lambda已经通过值捕获了结束迭代器,并且这个迭代器将永远不会自己更新。这适用于标准库中的每个容器,我猜它甚至可以容纳野外的每一个自定义容器。
当调用lambda时你取消引用了结束迭代器,这样做你就处于未定义的行为状态。你的程序是病态的,没有输出是有保证的。

nwnhqdif

nwnhqdif2#

“......当它可能不再是占位符时”(从评论到原始问题)是不正确的。

int test = 10;
void func(int a = test)
{
   std::cout << test << '\n';
}

int main()
{
   func();
   test = 100;
   func();
}

这里,输出为

10
100

基本上我的观点是,默认参数是在函数被调用时赋值的,因此,在您的示例中,it被赋值给列表的end迭代器,因此it->print()是未定义的行为,因为您使用it->print()解引用end迭代器(您可以将it->print()视为(*it).print(),但这可能是显而易见的)。

相关问题