簡體   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