為什么此代碼段有效?
#include <functional>
#include <iostream>
#include <memory>
int main()
{
std::unique_ptr<int> ptr(new int(666));
std::bind([](std::unique_ptr<int> &ptr){std::cout << *ptr << std::endl;}, std::move(ptr))();
}
您會看到 lambda 的引數應該是左值參考,而std::bind將右值(即std::move(ptr))傳遞給它。
另外,為什么這個代碼片段不能編譯?
std::function<void()> = std::bind([](std::unique_ptr<int> &ptr){std::cout << *ptr << std::endl;}, std::move(ptr));
僅僅因為std::function需要復制所有物件,而std::move(ptr)不能復制?
更新:
上述無法編譯的代碼見https://localcoder.org/how-to-capture-a-unique-ptr-into-a-lambda-expression(即見帖子中的“解決方案 3”)。所以上述解決方案是完全錯誤的。我對嗎?
uj5u.com熱心網友回復:
std::bind()不呼叫 lambda,它回傳一個代理,該代理將在稍后呼叫代理時呼叫 lambda。因此,僅僅因為您將右值參考傳遞給std::bind()并不意味著代理會將右值參考傳遞給 lambda。
而事實上,如果你仔細想想,代理無論如何也做不到。它必須將您的右值參考物件移動到代理中的某個物件中,以便在退出unique_ptr后將其保存以供以后使用。std::bind()并且某些東西本身不是右值,因此可以通過左值參考將某些東西傳遞給 lambda。
uj5u.com熱心網友回復:
std::bind 傳遞一個右值 ... 給它
是的,一個右值被傳遞給std::bind. 它被適當地藏起來以備不時之需,直到系結的可呼叫物件被呼叫為止。
那時,保存的物件通過參考傳遞給 lambda。
換句話說,以下是一個粗略的簡化,這就是這個特定的std::bind大致最終做出這樣的事情:
struct bound_function {
template<typename Arg> bound_function(Arg &&arg)
: saved_parameter{std::forward<Arg>(arg)}
{
}
void operator()()
{
invoke_bound_function(saved_parameter);
}
private:
std::unique_ptr<int> saved_parameter;
void invoke_bound_function(std::unique_ptr<int> &ptr){std::cout << *ptr << std::endl;}
};
將引數系結到可呼叫物件,然后使用系結引數呼叫可呼叫物件的行為是兩個離散的獨立事件。在第一個中,引數被移動到系結物件中,作為右值參考。
呼叫系結函式是一個單獨的步驟,系結引數通過參考傳遞給系結函式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/465307.html
