簡體   English   中英

如何將 std::unique_ptr 傳遞給 function

[英]How can I pass std::unique_ptr into a function

如何將std::unique_ptr傳遞給 function? 假設我有以下 class:

class A
{
public:
    A(int val)
    {
        _val = val;
    }

    int GetVal() { return _val; }
private:
    int _val;
};

以下不編譯:

void MyFunc(unique_ptr<A> arg)
{
    cout << arg->GetVal() << endl;
}

int main(int argc, char* argv[])
{
    unique_ptr<A> ptr = unique_ptr<A>(new A(1234));
    MyFunc(ptr);

    return 0;
}

為什么我不能將std::unique_ptr傳遞給 function? 這肯定是構造的主要目的嗎? 或者 C++ 委員會是否打算讓我回退到原始 C 樣式指針並像這樣傳遞它:

MyFunc(&(*ptr)); 

最奇怪的是,為什么這是一種通過它的好方法? 這似乎非常不一致:

MyFunc(unique_ptr<A>(new A(1234)));

這里基本上有兩種選擇:

通過引用傳遞智能指針

void MyFunc(unique_ptr<A> & arg)
{
    cout << arg->GetVal() << endl;
}

int main(int argc, char* argv[])
{
    unique_ptr<A> ptr = unique_ptr<A>(new A(1234));
    MyFunc(ptr);
}

將智能指針移動到函數參數中

請注意,在這種情況下,斷言將成立!

void MyFunc(unique_ptr<A> arg)
{
    cout << arg->GetVal() << endl;
}

int main(int argc, char* argv[])
{
    unique_ptr<A> ptr = unique_ptr<A>(new A(1234));
    MyFunc(move(ptr));
    assert(ptr == nullptr)
}

您通過值傳遞它,這意味着制作副本。 那不會很獨特吧?

您可以移動該值,但這意味着將對象的所有權及其生命周期的控制權傳遞給函數。

如果對象的生命周期保證在調用 MyFunc 的生命周期內存在,只需通過ptr.get()傳遞一個原始指針。

為什么我不能將unique_ptr傳遞給函數?

您不能這樣做,因為unique_ptr具有移動構造函數但沒有復制構造函數。 根據標准,當定義了移動構造函數但未定義復制構造函數時,將刪除復制構造函數。

12.8 復制和移動類對象

...

7 如果類定義未顯式聲明復制構造函數,則隱式聲明一個。 如果類定義聲明了移動構造函數或移動賦值運算符,則隱式聲明的復制構造函數被定義為已刪除;

您可以使用以下命令將unique_ptr傳遞給函數:

void MyFunc(std::unique_ptr<A>& arg)
{
    cout << arg->GetVal() << endl;
}

並像您一樣使用它:

或者

void MyFunc(std::unique_ptr<A> arg)
{
    cout << arg->GetVal() << endl;
}

並使用它:

std::unique_ptr<A> ptr = std::unique_ptr<A>(new A(1234));
MyFunc(std::move(ptr));

重要的提示

請注意,如果您使用第二種方法,則在調用std::move(ptr)返回后, ptr沒有指針的所有權。

void MyFunc(std::unique_ptr<A>&& arg)void MyFunc(std::unique_ptr<A>& arg)具有相同的效果,因為兩者都是引用。

在第一種情況下, ptr在調用MyFunc后仍然擁有指針的所有權。

為什么我不能將unique_ptr傳遞給函數?

您可以,但不能通過復制 - 因為std::unique_ptr<>不可復制構造。

這肯定是構造的主要目的嗎?

除其他外, std::unique_ptr<>旨在明確標記唯一所有權(與std::shared_ptr<> )。

最奇怪的是,為什么這是通過它的好方法?

因為在那種情況下,沒有復制構造。

由於MyFunc不擁有所有權,因此最好擁有:

void MyFunc(const A* arg)
{
    assert(arg != nullptr); // or throw ?
    cout << arg->GetVal() << endl;
}

或更好

void MyFunc(const A& arg)
{
    cout << arg.GetVal() << endl;
}

如果你真的想擁有所有權,你必須移動你的資源:

std::unique_ptr<A> ptr = std::make_unique<A>(1234);
MyFunc(std::move(ptr));

或直接傳遞 r 值引用:

MyFunc(std::make_unique<A>(1234));

std::unique_ptr沒有故意復制以保證只有一個所有者。

由於unique_ptr用於唯一所有權,如果您想將其作為參數傳遞,請嘗試

MyFunc(move(ptr));

但在那之后, mainptr的狀態將是nullptr

template<typename T> void MyFunc(T & arg)
{

  cout << arg->GetVal() << endl;

}

std::unique_ptr<T>作為值傳遞給函數不起作用,因為正如你們提到的, unique_ptr是不可復制的。

那這個呢?

std::unique_ptr<T> getSomething()
{
   auto ptr = std::make_unique<T>();
   return ptr;
}

此代碼正在工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM