初始化unique_ptr会导致AN&quot“错误:使用已删除函数”即使它s&quot s&quot std :: move”

发布于 2025-02-10 22:18:32 字数 2361 浏览 2 评论 0原文

我正在编写代码,该代码通过看起来不好的几层传递std :: unique_ptr,但是我别无选择,但现在一直通过它。

问题在于,当我尝试将std :: unique_ptr传递给提供者类的构造函数时,我会遇到错误。在Child :: function1()的点,child已使用inpland> impl&std的参数进行了初始化/构造:: Unique_ptr< retriever>来自其他地方。

有人可以告诉我为什么我会遇到这个错误,以及如何获得此工作?我想知道这是否是因为继承发生了,但是除了搬家以获得这项工作之外,我还不知道该怎么办与相同的构造函数...大声笑)

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

I am writing code that passes a std::unique_ptr through a few layers that look bad, but I don't have a choice but pass it all along for now.

The problem is that I am getting an error when I try to pass the std::unique_ptr to a constructor of the Provider class. At the point where Child::function1() is called, Child has been initialized/constructed with parameters of Impl& and std::unique_ptr<Retriever> from somewhere else.

Could someone please tell me why I'm getting this error, and how to get this work? I wonder if it's because of the inheritance happening, but I can't figure it out what else to do besides moving to get this work... (apart from something like not to pass this ptr through all these classes that seem to look similar with the same constructors... lol)

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

面如桃花 2025-02-17 22:18:32

Child :: function1()中,您正在将d_retriever_up by Value 传递给提供者构造函数。这需要制作d_retriever_up的副本,这是不可能的,因为它是unique_ptr具有delete> delete'd的复制构造函数,因此错误。

您需要使用std :: move()d_retriever_up移动到提供者中。您声称这样做,但您不是,至少不是在需要的任何地方。将呼叫者的unique_ptr移动到提供商 constructor的retriever_up参数是一个单独的操作,而不是将retriever_up参数移动到<<代码>提供商's d_retriever类成员。

但是,解决此问题后,您将遇到另一个问题。 child :: function1()被标记为const,它可以访问d_retriever_up be const> 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

In Child::function1(), you are passing d_retriever_up by value to the Provider constructor. That requires making a copy of d_retriever_up, which is impossible as it is a unique_ptr that has delete'd its copy constructor, hence the error.

You need to use std::move() to move d_retriever_up into Provider. You claim to be doing that, but you are not, at least not everywhere it is needed. Moving the caller's unique_ptr into the Provider constructor's retriever_up parameter is a separate operation than moving the retriever_up parameter into the Provider's d_retriever class member.

However, after you fix that, you will run into another problem. Child::function1() is marked asconst, which makes access to d_retriever_up be const in that context, so function1() can't modify d_retriever_up, including moves (since moving a unique_ptr sets its held pointer to nullptr).

So, to make the code work, you need to drop the const and add std::move():

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

That being said, moving d_retriever_up is questionable in your design. You might need to consider using std::shared_ptr instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文