如何使用lambdas和函数作为unique_ptr的自定义删除器

Fed*_*890 3 c++ lambda unique-ptr c++11

我正在测试自定义删除器unique_ptr.奇怪的是,只有作为功能对象的删除工作正常.如果我用函数或lambdas替换它们,程序不会编译.我究竟做错了什么?

这是我完整的测试程序

#include <iostream>
#include <memory>

using namespace std;


class Vehicle {
public:
    Vehicle(){ cout<<"Vehicle constructor..."<<endl;}
    virtual ~Vehicle(){cout<<"~Vehicle destructor..."<<endl;}
    virtual void go()=0;
};

class Car:public Vehicle {
    public:
    void go() override {
        cout<<"Going by car..."<<endl;
    }
};

class Bicycle:public Vehicle {
    public:
    void go() override {
        cout<<"Going by bicycle..."<<endl;
    }
};

// Custom deleters
auto CustomLambdaDeleter = [](Vehicle* v){
    cout<<"Custom lambda deleter called..."<<endl;
    delete v;
};

void CustomFunctionDeleter(Vehicle* v){
    cout<<"Custom function deleter called..."<<endl;
    delete v;
}

struct CustomFunctorDeleter
{
    void operator()(Vehicle* v ) const {
        cout<<"Custom functor deleter called..."<<endl;
        delete v;
    }
};


// Doesn't compile
//using VehiclePtr = unique_ptr<Vehicle, decltype(CustomLambdaDeleter)>;
// Doesn't compile
//using VehiclePtr = unique_ptr<Vehicle, decltype(&CustomFunctionDeleter)>;
// Works ok
using VehiclePtr = unique_ptr<Vehicle, CustomFunctorDeleter>;


class VehicleFactory {
public:
    static VehiclePtr createVehicle(string type){
        VehiclePtr vptr;
        if("bicycle"==type) {
            vptr.reset(new Bicycle());
            // This also works
            // vptr= (VehiclePtr) new Bicycle();
            return vptr;
        }
        else if("car"==type) {

           vptr.reset( new Car());
           return vptr;
        }

        return nullptr;
    }
};


void vehicleFactoryTest(){
    cout<<"* Starting vehicleFactoryTest()..."<<endl;
    auto firstVehicle = VehicleFactory::createVehicle("bicycle");
    firstVehicle->go();
    auto newCar = VehicleFactory::createVehicle("car");
    newCar->go();
}

int main(int, char **)
{

    vehicleFactoryTest();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Pra*_*ian 5

问题不在于任何一个

using VehiclePtr = unique_ptr<Vehicle, decltype(CustomLambdaDeleter)>;
Run Code Online (Sandbox Code Playgroud)

要么

using VehiclePtr = unique_ptr<Vehicle, CustomFunctorDeleter>;
Run Code Online (Sandbox Code Playgroud)

那两个自己编译.问题在于以下内容createVehicle

VehiclePtr vptr;
Run Code Online (Sandbox Code Playgroud)

在这里,你是默认构造一个unique_ptr,在lambda删除器的情况下不会编译,因为lambdas不是默认构造的.所以你需要

VehiclePtr vptr{nullptr, CustomLambdaDeleter};
Run Code Online (Sandbox Code Playgroud)

在您使用函数指针的情况下,您尝试默认unique_ptr使用nullptr删除器构造它,这是不允许的.修复方法类似,在这种情况下需要传递指向函数的指针.

VehiclePtr vptr{nullptr, CustomFunctionDeleter};
Run Code Online (Sandbox Code Playgroud)

你也在最后的return语句中犯了类似的错误createVehicle.将该行更改为

return vptr;
Run Code Online (Sandbox Code Playgroud)