【问题标题】:Unique_ptr with lambda deleter带有 lambda 删除器的 Unique_ptr
【发布时间】:2017-07-18 10:29:12
【问题描述】:

我有一些函数需要使用成员变量(自定义类的向量)。
在这个函数结束时,这个成员需要被清除,但它需要在这个函数的持续时间内保持成员身份。 另一个问题是,由于程序的自定义错误处理,函数可能会提前结束。然而,该成员仍然需要被清除。

使用Ron's advice in this postthis so post我得到以下代码:

#include <iostream>
#include <vector>
#include <memory>
using namespace std;

class A
{
public:
    A()
    {
        m_numbers = { { 3, 1 ,4, 1, 5} };
    }

    void display()
    {
        auto cleanNumber = [](decltype(m_numbers)* numbers){ 
            if(numbers) 
                move(*numbers);
        };
        auto pClean = std::unique_ptr<decltype(m_numbers), decltype(cleanNumber)>(&m_numbers);
        for(int number: m_numbers)
            cout << number << endl;
    }
private:
    vector<int> m_numbers;
};

int main()
{
    A a;
    a.display();
    cout << "should be empty now" << endl;
    a.display();
    return 0;
}

这会产生以下错误:(抱歉格式化)

g++ -std=c++17 -o main2 main2.cpp                                   
In file included from d:\program files\minggw\lib\gcc\mingw32\5.3.0\include\c++\memory:81:0, from main2.cpp:3:
d:\program files\minggw\lib\gcc\mingw32\5.3.0\include\c++\bits\unique_ptr.h: 
In instantiation of 'std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) 
[with _Tp = std::vector<int>; _Dp = A::display()::<lambda(std::vector<int>*)>; std::unique_ptr<_Tp, _Dp>::pointer = std::vector<int>*]':
main2.cpp:20:87:   required from here 
d:\program files\minggw\lib\gcc\mingw32\5.3.0\include\c++\bits\unique_ptr.h:170:33: 
error: use of deleted function 'A::display()::<lambda(std::vector<int>*)>::<lambda>()'
: _M_t(__p, deleter_type()) 
 main2.cpp:16:23: note: a lambda closure type has a deleted default constructor
 auto cleanNumber = [](decltype(m_numbers)* numbers){

我想我明白我不能传递这个 lambda 的 decltype,因为默认构造函数已被删除。那我该如何传递正确的 lambda 删除器呢?

环顾四周,我来到this answer,这似乎是等价的,但我不明白为什么它会起作用以及我的代码有何不同?

n.b.我不确定我是否应该编辑我原来的问题。 我认为这不是澄清,而是寻求进一步的建议,所以我提出了一个新问题,希望这符合规则。

【问题讨论】:

  • 几件事:看起来你想实现一个scope guard,你真的不需要为此使用unique_ptr!其次,只调用 move(*numbers) 什么都不做,您需要将此值分配给稍后将被删除的某个局部变量。第三,你需要在你的 unique_ptr 中明确指定你的删除器,就像已经提到的 VTT
  • @TobiasRibizel 我现在正在阅读范围警卫,我认为这可能是this question的答案
  • @TobiasRibizel 我阅读了范围保护链接,虽然它看起来确实是我想要的,但除非有一些标准实现的范围保护,否则我看不出这会更好。
  • 据我所知,std 库中没有通用的实现,但是为此使用unique_ptr 是解决原始问题的一种相当丑陋的方法。如果更频繁地需要这样的范围保护,添加一个简单的 10 行实现不会有什么坏处;)
  • 美女在旁观者的眼中,我发现额外的班级比这更丑。然而,如果我需要在不同的地方使用它,我可能会为它添加一个单独的类,就像我最初在被指向这个解决方案之前所做的那样。

标签: c++ lambda


【解决方案1】:

您需要将cleanNumber 传递给unique_ptr 构造函数:

auto pClean = std::unique_ptr<decltype(m_numbers), decltype(cleanNumber)>(&m_numbers, cleanNumber);

您的 lambda 也不会清除矢量内容,因为 move(*numbers); 什么也不做。你应该改写numbers-&gt;clear();

【讨论】:

  • 谢谢,就是这样。清除确实在这里更好。我仍然使用 move 作为重构工件,但现在没有必要了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-15
  • 2013-07-03
  • 2019-01-16
  • 2016-11-23
  • 1970-01-01
  • 2015-09-11
  • 2012-04-11
相关资源
最近更新 更多