[英]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));
但在那之后, main
中ptr
的狀態將是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.