std :: move会使指针无效吗?

Jan*_*han 7 c++ pointers move

假设如下:

template<typename Item>
class Pipeline
{
    [...]

    void connect(OutputSide<Item> first, InputSide<Item> second)
    {
        Queue<Item> queue;
        first.setOutputQueue(&queue);
        second.setInputQueue(&queue);
        queues.push_back(std::move(queue));
    }

    [...]

    std::vector<Queue<Item> > queues;
};
Run Code Online (Sandbox Code Playgroud)

移动后,指向队列的指针仍会在"第一个"和"第二个"中工作吗?

Mik*_*our 11

std :: move会使指针无效吗?

否.移动后对象仍然存在,因此任何指向该对象的指针仍然有效.如果Queue合理地实施,那么从它移动应该使其处于有效状态(即,销毁或重新分配它是安全的); 但可能会改变其状态(可能会将其留空).

移动后,指向队列的指针仍会在"第一个"和"第二个"中工作吗?

不会.他们会指向被移走的本地物体; 如上所述,您不能在移动后对该对象的状态做出任何假设.

更糟糕的是,当函数返回时,它被破坏,让指针悬空.它们现在无效,不指向任何对象,使用它们将给出未定义的行为.

也许你希望他们指向被移入的对象queues:

queues.push_back(std::move(queue));
first.setOutputQueue(&queue.back());
second.setInputQueue(&queue.back());
Run Code Online (Sandbox Code Playgroud)

但是,由于queues是一个向量,当队列接下来重新分配其内存时,这些指针将无效.

要解决该问题,请使用类似容器dequelist插入后不移动其元素的容器.或者,以额外的间接级别为代价,您可以存储(智能)指针而不是对象,如Danvil的回答中所述.


Dan*_*vil 5

指针将不起作用,因为它queue是一个本地对象,将在末尾删除connect。即使通过使用,std::move您仍将在新的内存位置创建一个新对象。它只会尝试从“旧”对象中使用尽可能多的内容。

另外,整个事情将完全无法独立于使用std::movepush_back不得不重新分配。因此,对的调用connect可能会使您所有的旧指针失效。

一种可能的解决方案是Queue在堆上创建对象。以下建议使用C ++ 11:

#include <memory>

template<typename Item>
class Pipeline
{
    [...]

    void connect(OutputSide<Item> first, InputSide<Item> second)
    {
        auto queue = std::make_shared<Queue<Item>>();
        first.setOutputQueue(queue);
        second.setInputQueue(queue);
        queues.push_back(queue);
    }

    [...]

    std::vector<std::shared_ptr<Queue<Item>>> queues;
};
Run Code Online (Sandbox Code Playgroud)