为什么我不能在C ++ 14的lambda中移动std :: unique_ptr? [英] Why can't I move the std::unique_ptr inside lambda in C++14?

查看:204
本文介绍了为什么我不能在C ++ 14的lambda中移动std :: unique_ptr?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在lambda内部传递一个原始指针,但是如果不调用lambda,我不希望它被泄漏.看起来像这样:

I want to pass a raw pointer inside lambda, but I don't want it to be leaked, if the lambda isn't invoked. It looks like this:

void Clean(std::unique_ptr<int>&& list);

void f(int* list) {
  thread_pool.Push([list = std::unique_ptr<int>(list) ] {
    Clean(std::move(list));  // <-- here is an error.
  });
}

我在Clang 3.7.0中遇到错误:

I get an error in Clang 3.7.0:

错误:将对"unique_ptr< [2 * ...]>"类型的引用绑定到"unique_ptr< [2 * ...]>"类型的值会丢弃限定符

error: binding of reference to type 'unique_ptr<[2 * ...]>' to a value of type 'unique_ptr<[2 * ...]>' drops qualifiers

但是我没有看到任何预选赛,特别是掉线的比赛.

But I don't see any qualifiers at the first place, especially dropped.

此外,我发现了类似的报告在邮件列表中,但没有答案.

Also, I found similar report on the mailing list, but without answer.

我应该如何修改我的代码,使其能够按语义期望地进行编译并正常工作?

How should I modify my code, so it gets compiled and works as expected by semantics?

推荐答案

您需要制作内部lambda mutable:

You need to make the inner lambda mutable:

[this](Pointer* list) {
  thread_pool.Push([this, list = std::unique_ptr<int>(list) ]() mutable {
                                                               ^^^^^^^^^
    Clean(std::move(list));
  });
};

默认情况下,lambdas上的

operator()const,因此您无法在该调用中修改其成员.这样,内部list的行为就好像它是const std::unique_ptr<int>一样.当您执行move强制转换时,它将转换为const std::unique_ptr<int>&&.这就是为什么出现有关删除限定符的编译错误的原因:您试图将 const 右值引用转换为非常量右值引用.该错误可能没有提供应有的帮助,但最终可以归结为:您不能move一个const unique_ptr.

operator() on lambdas is const by default, so you cannot modify its members in that call. As such, the internal list behaves as if it were a const std::unique_ptr<int>. When you do the move cast, it gets converted to a const std::unique_ptr<int>&&. That's why you're getting the compile error about dropping qualifiers: you're trying to convert a const rvalue reference to a non-const rvalue reference. The error may not be as helpful as it could be, but it all boils down to: you can't move a const unique_ptr.

mutable修复了-operator()不再是const,因此该问题不再适用.

mutable fixes that - operator() is no longer const, so that issue no longer applies.

注意:如果您的Clean()使用了unique_ptr<int>而不是unique_ptr<int>&&,这更有意义(因为它是更明确的确定性接收器),那么错误将会更加明显:

Note: if your Clean() took a unique_ptr<int> instead of a unique_ptr<int>&&, which makes more sense (as it's a more explicit, deterministic sink), then the error would have been a lot more obvious:

error: call to deleted constructor of `std::unique_ptr<int>`
note: 'unique_ptr' has been explicitly marked deleted here  

    unique_ptr(const unique_ptr&) = delete
    ^

这篇关于为什么我不能在C ++ 14的lambda中移动std :: unique_ptr?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆