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

时间:2017-01-17 17:29:21

标签: c++ c++11 lambda unique-ptr

我正在测试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;
}

1 个答案:

答案 0 :(得分:5)

问题不在于

using VehiclePtr = unique_ptr<Vehicle, decltype(CustomLambdaDeleter)>;

using VehiclePtr = unique_ptr<Vehicle, CustomFunctorDeleter>;

这两个人自己编译。问题在于createVehicle

中的以下行
VehiclePtr vptr;

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

VehiclePtr vptr{nullptr, CustomLambdaDeleter};

如果您正在使用函数指针,则您尝试使用unique_ptr删除操作默认构造nullptr,这是不允许的。修复方法类似,在这种情况下你需要传递一个指向函数的指针。

VehiclePtr vptr{nullptr, CustomFunctionDeleter};

您还在createVehicle的最终回复语句中犯了类似的错误。将该行更改为

return vptr;