【问题标题】:Check if std::move is done on container检查 std::move 是否在容器上完成
【发布时间】:2015-03-27 06:06:12
【问题描述】:

有什么方法可以检查某些 STL 容器上的 std::move 是否完成?

我有两种类型的类(比如说 A 和 B),它们将另一个类的(一些)实例保存在它们的内部容器中。如果 A 的实例在其容器中保留 B 的实例,则 B 的实例也必须在其容器中保留相同的 A 实例。

A 可以看到 B 的私有方法(B 有它的朋友),但我必须在 B 上实现移动构造函数。由于 B 可以看到两者的内部容器,我已经实现了 B 对两个类的所有添加和删除。

问题是:
我必须为 A 实现移动构造函数,并在该容器上使用 stl::move。将容器移动到 A 的新实例后,通知 B 旧类分离的唯一方法是通过使用 B 和旧 A 的容器并同时删除两个类的方法。
B 有什么方法可以知道旧 A 的容器已移动并且它不应该访问它?
它无需检查即可工作,但由于类在 std::move 之后没有定义状态,我不应该在其上调用 ::remove()(教授说这是一个错误)。
请注意:这是我的作业问题,所以我不希望获得解决完整问题的非法帮助,仅检查对象一致性的部分以跳过移动后调用它的函数。

编辑:添加示例。
重要提示:
1) 我需要使用 std::move。我已经知道使用迭代器在 while 循环中完成所有操作的简单方法。但是,明确要求 std::move。
2)这个sn-p是为了理解我的问题。作为学生,我想自己解决,我只需要信息如何在不允许的情况下跳过一行。

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
    //...
};

【问题讨论】:

  • 您应该尝试编写一个简短的代码示例来显示您正在尝试执行的操作。描述有点复杂。
  • 感谢您的建议。我已经添加了代码。
  • 对我来说,仅仅给出一个提示几乎是不可能的,因为这个设计似乎有问题,应该重新改造逻辑。例如:在A(A &amp;&amp; a) 中,您使用a.remove(*b);,这对我来说意义不大,而且A::remove 与您显示的不同,因为显示的是A::remove(A*),而调用的是A::remove(B),除非有一些转换路径。
  • 你确定,你能指定行吗?此代码在我的编译器上编译并完美运行(正确的类在所有操作之后都包含正确的类)。唯一的问题是,由于我指定的行有时应该被跳过,所以理论上它是不可行的。如果你的意思是应该改变逻辑来做到这一点,那么我理解它。否则,它只是因为实现是自然的和预期的,但没有指定。
  • 以下是您可以使用已移动的 std::container 执行的操作:stackoverflow.com/a/7028318/576911

标签: c++ c++11 std move


【解决方案1】:

有什么方法可以检查某些 STL 容器上的 std::move 是否完成?

std::move 模板不会移动任何东西,它只是

获取对其参数的右值引用并将其转换为 极值。

如果编译类似于b_container(std::move(a.b_container)) 的代码,则std::move“工作”并且b_container 具有移动构造函数,并且移动构造函数移动指定为参数的对象的内部。否则代码不可编译。由于缺少移动构造函数,以下示例无法编译。 Here 在大肠杆菌上。

#include <utility>

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

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

总结以上文字。 std::move 总是“有效”。

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

B 有什么办法可以知道旧 A 的容器被移动了,它不应该访问它?

没有办法检查旧容器是否被移动,即检查它的状态。但是可以访问它,例如调用std::vector::empty 方法,因为该对象是有效的。有关说明,请参阅this link。

【讨论】:

  • Thanx,在您的最后一个链接(以及来自 c++ 文档)上,我看到对象的状态无效,但未知,因此我无法继续调用简单的函数。感谢您提供广泛的文献,但这仍然不能解决我的问题。
  • @tbukic 我的回答可以回答您的问题。你写了I'd like to solve it by myself。据我了解,您只需要问题的答案,并没有现成的问题解决方案。
  • 你是对的(“问题”,在最后的评论中,我的意思是“在可能出现问题时找到跳线的方法”:D)。并且 - 再次感谢。 =)在您的链接上,我发现我的代码(如果容器类仍处于有效状态)可以在没有任何更改的情况下运行正常,但是从您上一个链接的(彩色)部分和我的教授的建议来看,我得出的结论会更好避免使用 move-from,因此对于每种情况,我都以更丑陋但更安全的方式实现了它。
猜你喜欢
  • 2016-12-19
  • 2015-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-05
  • 2019-03-21
  • 1970-01-01
相关资源
最近更新 更多