检查是否在容器上执行了std::move

3
有没有办法检查 STL 容器是否已经使用了 std::move?
我有两种类型的类(假设为 A 和 B),它们在其内部容器中保留另一个类的实例。如果 A 的实例在其容器中保留 B 的实例,则该 B 的实例也必须在其容器中保留相同的 A 实例。
A 可以看到 B 的私有方法(B 将其作为友元),但我必须在 B 上实现移动构造函数。由于 B 可以看到两个类的内部容器,因此我已经实现了 B 来执行两个类的所有添加和删除操作。
问题是:
我必须为 A 实现移动构造函数,并在该容器上使用 stl::move。将容器移动到新的 A 实例后,通知旧类分离的唯一方法是通过使用 B 的方法,旧 A 的容器并对两个类进行删除。
有没有办法让 B 知道旧 A 的容器已被移动,不能访问它?
没有检查也可以工作,但由于类在 std::move 后没有定义状态,所以不应调用 ::remove()(教授说这是错误的)。
请注意:这是我的家庭作业问题,因此我不希望获得解决完整问题的非法帮助,只需要检查对象的一致性部分以跳过调用其函数。
编辑:添加示例。
重要:
1)我需要使用 std::move。我已经知道使用迭代器在 while 循环中完成所有操作的简单方法。但是,明确要求使用 std::move。
2)此代码片段是为了理解我的问题。作为学生,我想自己解决它,我只需要了解如何在不允许时跳过执行一行即可。
class A;

class B {
public:
    // ...... some constructors, functions and destructor.
    void add(A *a) {
        // .. adds to both containers.
    };
    void remove(A *a) { // I need to remove from both containers at most of the times
        a_container.erase(a);
        a->b_container.erase(this); // PROBLEM(!!): after doing std::move(b_container) I shouldn't do this! How to check is b_container moved?
    };
private:
    std::_______<A*> a_container; //type of container is not important
};

class A {
    friend class B;
public:
    // ...... some constructors, functions and destructor.
    A(A && a) :
        b_container(std::move(a.b_container)) {
        //..
        for (B *b : b_container) {
            b->add(this); //adds to B's connected to the old instance
            a.remove(*b); //I need somehow to disconect old B's from pointer of moved A.
        }
    };
    void add(B & b) {
        b.add(this);
    };
    void remove(B & b) {
        b.remove(this);
    };
private:
    std::_______<B*> b_container; //type of container is not important
    //...
};

你应该尝试编写一个简短的代码示例,展示你想要做什么。描述有些复杂。 - Retired Ninja
谢谢您的建议。我已经添加了代码。 - mr.engineer
对我来说,仅仅给出一个提示是相当困难的,因为这个设计似乎有缺陷,逻辑应该重新设计。例如:在 A(A && a) 中,你使用了 a.remove(*b);,这对我来说没有多少意义,而且它与你展示的 A::remove 不同,因为展示的是 A::remove(A*),而调用的是 A::remove(B),除非有某种转换路径。 - luk32
你确定吗?能具体说明一下是哪一行吗?这段代码在我的编译器上编译并运行得非常完美(正确的类在所有操作后都包含正确的内容)。唯一的问题是,由于我指定的那一行有时应该被跳过,所以从理论上讲它并不完全正确。如果你的意思是要改变逻辑来实现这一点,那么我理解。否则,它只是因为自然而然的实现和预期的结果才能正常工作,但并没有明确规定。 - mr.engineer
以下是您可以使用已移动的std::容器执行的操作:https://dev59.com/rGw05IYBdhLWcg3wykzn#7028318 - Howard Hinnant
1个回答

1

有没有办法检查STL容器上是否进行了std::move操作?

std::move模板并不会移动任何东西,它只是获取其参数的右值引用并将其转换为xvalue。

如果类似于b_container(std::move(a.b_container))的代码被编译,则std::move“起作用”,b_container具有移动构造函数,并且该移动构造函数移动了指定为参数的对象的内部。否则代码无法编译。由于缺少移动构造函数,以下示例无法编译。这里是在coliru上的示例。

#include <utility>

class B {
public:
    B() = default;
    B(B &&) = delete;
};

int main() {
    B b0;
    B b1(std::move(b0));
    return 0;
}

总结以上内容。 std::move 总是“有效”的。

移动后的对象状态未指定。 链接#00链接#01 解释了这种行为。

B 有没有办法知道旧的 A 的容器已经移动,不能再访问它?

没有办法检查旧容器是否已经移动,即无法检查其状态。但可以访问它,例如调用 std::vector::empty 方法,因为该对象是有效的。请参见此链接以获取说明。


谢谢,从您最后提供的链接(以及C++文档)中我看到对象的状态无效,而是未知的,因此我甚至不能调用简单的函数。感谢您提供丰富的文献资料,但这仍然没有解决我的问题。 - mr.engineer
@tbukic,我的回答已经回答了你的问题。你写道 "我想自己解决它"。据我所理解,你只需要问题的答案,而没有准备好的解决方案。 - megabyte1024
你说得对(在上次评论中,“问题”是指“找到跳过可能存在问题的行的方法”:D)。感谢你再次帮助我。通过你提供的链接,我发现如果容器类仍处于有效状态,则我的代码将无需任何更改即可正常运行,但从你最后一个链接中突出显示的部分以及我的教授的建议中,我断定最好不要使用moved-from,因此针对每种情况,我都采用了更丑陋但更安全的方法来实现它。 - mr.engineer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接