繁体   English   中英

初始化 unique_ptr 会导致“错误:使用已删除函数”,即使它是“std::move”ed

[英]Initializing unique_ptr causes an "error: use of deleted function" even though it's "std::move"ed

我正在编写将std::unique_ptr传递给看起来很糟糕的几层的代码,但我别无选择,只能暂时传递它。

问题是当我尝试将std::unique_ptr传递给Provider类的构造函数时出现错误。 在调用Child::function1()时, Child已使用Impl&std::unique_ptr<Retriever>的参数从其他地方初始化/构造。

有人可以告诉我为什么会出现此错误,以及如何完成这项工作吗? 我想知道这是否是因为发生了继承,但我不知道除了移动来完成这项工作之外还能做什么......(除了不通过所有这些看起来相似的类传递这个 ptr使用相同的构造函数...大声笑)

// child.cpp
Child::Child(Impl& child_impl, std::unique_ptr<Retriever> child_retriever_up)
: Parent(child_impl, std::move(child_retriever_up))
{}

T::Y Child::function1() const
{
    **Provider provider(d_impl, d_retriever_up);** 
    // these d_impl and d_retriever are in Parent class.
    ...
    return Y;
}

// child.h
class Child : public Parent {
public:
    // creators
    explicit Child(Impl& child_impl, std::unique_ptr<Retriever> child_retriever_up);
    ~Child() override = default;
    // accessors
    T::Y Child::function1() const;
private:
    Child(const Child&) = delete;
    Child& operator=(const Child&) = delete;
// parent.cpp
Parent::Parent(Impl& impl, std::unique_ptr<Retriever> retriever_up)
: d_impl(impl), d_retriever_up(std::move(retriever_up))
{}

// parent.h
class Parent {
public:
    // creators
    explicit Parent(Impl& impl, std::unique_ptr<Retriever> retriever_up);
    virtual ~Parent() = default;
    // copy constructor
    Parent(const Parent& parent) 
    : d_context(parent.d_impl)
    , d_retriever_up(std::move(*parent.d_retriever_up))
    {
    }
    // data
    Impl& d_impl;
    std::unique_ptr<Retriever> d_retriever_up;
private:
    //Parent(const Parent&) = delete;
    Parent& operator=(const Parent&) = delete;
// provider.cpp
Provider::Provider(Impl& impl, std::unique_ptr<Retriever> retriever_up)
: d_impl(impl)
, d_retriever(std::move(retriever_up))
{}

// provider.h
class Provider {
public:
    Provider(Impl& context, std::unique_ptr<Retriever> retriever_up);
    //copy contstructor
    Provider(const Provider& provider) 
    : d_impl(provider.d_impl)
    , d_retriever(std::move(*provider.d_retriever))
    {
    }

private:
    Impl& d_impl;
    std::unique_ptr<Retriever> d_retriever;
}

Child::function1()中,您将d_retriever_up按值传递给Provider构造函数。 这需要制作d_retriever_up的副本,这是不可能的,因为它是一个unique_ptr ,它具有delete 'd 其复制构造函数,因此会出现错误。

您需要使用std::move()d_retriever_up移动到Provider 你声称正在这样做,但你不是,至少不是在所有需要它的地方。 将调用者的unique_ptr移入Provider构造函数的retriever_up参数与将retriever_up参数移入Providerd_retriever类成员是一个单独的操作。

但是,在你修复它之后,你会遇到另一个问题。 Child::function1()被标记为const ,这使得在该上下文中对d_retriever_up的访问为const ,因此function1()不能修改d_retriever_up ,包括移动(因为移动unique_ptr会将其持有的指针设置为nullptr )。

因此,要使代码正常工作,您需要删除const并添加std::move()

T::Y Child::function1()
{
    Provider provider(d_impl, std::move(d_retriever_up));
    ...
    return Y;
}

话虽如此,在您的设计中移动d_retriever_up是有问题的。 您可能需要考虑改用std::shared_ptr

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM