无效迭代器上的算术运算

问题描述 投票:2回答:1

是行为的 std::distance 未定义,当调用一对 std::vector 迭代器,这些迭代器因移动了 vector?

对于上下文:我正在为一个类编写复制和移动构造函数,这个类有一个 vector 的数据和一个 vector 的迭代器,指向该数据。一旦我将数据移动到目的地,我需要将迭代器的向量翻译成指向新的容器。我希望避免在内存中创建中间索引表示。

c++ vector iterator invalidation
1个回答
1
投票

的行为是 std::distance 未定义,当调用一对 std::vector 迭代器,这些迭代器因移动了 vector?

如果迭代器在移动前是有效的,那么在移动后它们将继续有效--所以你不需要使用 std::distance.

(着重说明)

标准::向量::向量

容器移动构造后,引用、指针。和迭代器 迭代器以外)到 other 仍然有效,但指的是现在在的元素。*this.

目前的标准是通过以下的空白声明来保证的。[容器.要求.一般12]目前正在考虑通过以下方式提供更直接的担保 LWG 2321.

[容器.要求.一般12] 指出

除非另有规定(无论是显式的还是用其他函数定义的),否则调用容器成员函数或将容器作为参数传给库函数 不得使迭代器无效 的值,或改变该容器内对象的值。

同样的空白语句也适用于移动赋值操作符,这意味着,根据标准,迭代符 搬迁后继续有效。

目前的措辞是 LWG 2321 给出了一个提示,如果库工作组最终确定这个标准中的新段落会是什么样子--这似乎很难。LWG 2321早在2013年就开始了。

没有移动构造函数(或移动赋值操作符,当 allocator_traits<allocator_type>::propagate_on_container_move_assignment::valuetrue)的容器(除了 array)使任何指向源容器元素的引用、指针或迭代器无效。[注: 该项 end() 迭代器并不指向任何元素,所以它可能无效。— 尾注]

如果太含糊,你可以使用

[容器.要求.一般11.6]

swap() 函数使任何引用、指针无效。或迭代器 指的是被交换的容器的元素。[ 注: end() 迭代器没有引用任何元素,所以可能无效。- 尾注 ]

如果迭代器有效 之前swap,它们是有效的 之后swap.

下面是一个使用给定的保证的示例类 swap:

#include <vector>

class Foo {
    std::vector<int> data{};
    std::vector<decltype(data)::iterator> dits{};

public:
    Foo() = default;

    Foo(const Foo&) = delete;    // here, dits would need to be calculated

    // A move constructor guaranteed to preserve iterator validity.
    Foo(Foo&& rhs) noexcept {
        data.swap(rhs.data);
        dits.swap(rhs.dits);
    }

    Foo& operator=(const Foo&) = delete;

    // A move assignment operator guaranteed to preserve iterator validity.
    Foo& operator=(Foo&& rhs) noexcept {
        data.swap(rhs.data);
        dits.swap(rhs.dits);
        return *this;
    }

    ~Foo() = default;
};
© www.soinside.com 2019 - 2024. All rights reserved.