为什么放在deque类中的共享指针在初始化期间会获得读访问冲突?

Yu *_*ato 1 c++ c++11

以下代码生成An exception was thrown: a read access violation. This was 0xFFFFFFFFFFFFFFF7错误:

    std::deque<std::shared_ptr<int>> a(10);
    std::deque<std::shared_ptr<int>> b(&a[0], &a[2]);
Run Code Online (Sandbox Code Playgroud)

但是使用int以下代码中的as,它可以正常工作.

    std::deque<int> a(10);
    std::deque<int> b(&a[0], &a[2]);
Run Code Online (Sandbox Code Playgroud)

我尝试的其他初始化也是如此:

    std::deque<std::shared_ptr<int>> a(10, std::make_shared<int>(1));
    std::deque<std::shared_ptr<int>> b(&a[0], &a[2]);
Run Code Online (Sandbox Code Playgroud)

为什么是这样?

Fan*_*Fox 7

你在做什么实际上是未定义的行为.

当您执行此b(&a[0], &a[2])构造函数(使用范围的内容构造)时,您将迭代迭代deque器而不是迭代器,而是通过对每个成员内存位置的引用.你不会从指针获得连续的迭代器.

A deque在内存中不一定是连续的(例如,如果它是像你的情况那样实现为链表).这意味着您可能会取消引用您不拥有的内存.它也出现在第二个示例中,但您没有看到它,因为行为未定义.

        Link               Link
    _____________    _______________    ______ ...
  |                |                  |
&a[0] [other mem] &a[1] [other mem] &a[2]   ...
       //^^^^^^^
       // When you iterate in b(&a[0], &a[2]), you iterate over this memory you dont own!
Run Code Online (Sandbox Code Playgroud)

它可以做任何事情,包括An exception was thrown: a read access violation.像你在你的情况下那样正确地投掷甚至工作.在这里阅读有关未定义的行为.

您可以使用以下命令正确初始化:

std::deque<std::shared_ptr<int>> b(a.begin(), a.begin() + 2);
Run Code Online (Sandbox Code Playgroud)

在这里查看一个实例.