如何在 std::for_each 中捕获 lambda 的 std::unique_ptr "by move"
How to capture std::unique_ptr "by move" for a lambda in std::for_each
我正在学习 c++11 中的新功能,遇到了这个问题。 我想通过将unique_ptr移动到 lambda 中作为for_each的参数来捕获它。
建立:
std::array<int,4> arr = {1,3,5,6};
std::unique_ptr<int> p(new int); (*p) = 3;
尝试 1 - 不起作用,因为unique_ptr没有复制构造函数。 C++0x 不指定"按移动传递"语法。
std::for_each(arr.begin(), arr.end(), [p](int& i) { i+=*p; });
尝试 2 - 使用 bind 将移动的 P 副本绑定到采用 int&的函数:
std::for_each(arr.begin(), arr.end(),
std::bind([](const unique_ptr<int>& p, int& i){
i += (*p);
}, std::move(p))
);
编译器抱怨'result' : symbol is neither a class template nor a function template.
本练习的主要目的是了解如何在缓存以供以后使用的 lambda 中捕获可移动变量。
更新:您可以从 C++14 开始在 lambda 中捕获可移动变量。
std::for_each(arr.begin(), arr.end(), [p=std::move(p)](int& i) { i+=*p; });
在 C++11 中,您无法以任何直接的方式将可移动变量捕获到 lambda 中。
通过复制或引用捕获 Lambda。因此,要捕获仅移动变量,必须将其包装在复制 => 移动的对象中(例如 std::auto_ptr
)。这是一个令人讨厌的黑客。
在您的示例中,您可以仅通过引用捕获,但如果这只是简化的代码,则可能无法使用实际代码执行您想要的操作:
std::for_each(arr.begin(), arr.end(), [&p](int& i) { i+=*p; });
这是一个仅复制移动包装器:
template<typename T>
struct move_on_copy_wrapper
{
mutable T value;
move_on_copy_wrapper(T&& t):
value(std::move(t))
{}
move_on_copy_wrapper(move_on_copy_wrapper const& other):
value(std::move(other.value))
{}
move_on_copy_wrapper(move_on_copy_wrapper&& other):
value(std::move(other.value))
{}
move_on_copy_wrapper& operator=(move_on_copy_wrapper const& other)
{
value=std::move(other.value);
return *this;
}
move_on_copy_wrapper& operator=(move_on_copy_wrapper&& other)
{
value=std::move(other.value);
return *this;
}
};
然后,您可以像这样使用它:
int main()
{
std::unique_ptr<int> p(new int(3));
move_on_copy_wrapper<std::unique_ptr<int>> mp(std::move(p));
[mp]()
{
std::cout<<"*mp.value="<<*mp.value<<std::endl;
}
();
std::cout<<"p="<<p.get()<<", mp="<<mp.value.get()<<std::endl;
}
您的尝试 2 几乎可以工作。
缺少的是你没有告诉你的bind
调用需要一个参数:
std::for_each(arr.begin(), arr.end(),
std::bind([](const unique_ptr<int>& p, int& i){
i += (*p);
}, std::move(p), std::placeholders::_1)
);
placeholders::_1
有必要告诉 bind
的结果,它应该期望传递给它的参数以operator()
。
这也是@marton78在这里回答时给出的建议。
相关文章:
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 为什么 std::unique 不调用 std::sort?
- 我对 std::unique(算法)C++有问题
- std::shared_ptr::unique(),复制和线程安全
- 如何在C++03中用自定义谓词调用std::unique
- C++ std::unique并没有显示我对它的期望
- C++14 unique_ptr并使用已删除的函数'std::unique-ptr' unique_ptr错误
- 为什么 [std::unique] 不能应用于 [std::multiset]?
- 使用 std::unique 和 vector.erase 删除除最后一次出现的重复元素之外的所有元素
- 是否可以在 std::unique<T[ ]> 上应用 std::sort?
- std::unique 是否有大小限制
- 从 std::unique 返回的迭代器的用法
- 使 std::unique<T> 与 std::unique<const T, CustomDeleterType 兼容>
- Std::list.unique()应该使迭代器无效
- 无法使用初始化器列表构造 vector<std::unique<...>>
- 从自定义对象- std:unique的向量中消除重复项会导致崩溃
- 我能保证std::unique将保留第一个元素吗?
- 在 std::vector<std::unordered_set上使用 std::unique(<T>>