条款18:对独占资源使用std::unique_ptr

一、默认情况下 unique_ptr 大小等同于原始指针

unique_ptr 不允许拷贝,只允许移动。(移动之后,源指针被设置为nullptr)

std::unique_ptr<Test> uptr = std::unique_ptr<Test>(new Test(10));
auto size = sizeof(uptr);
std::unique_ptr<Test> uptr1 = std::move(uptr);
std::shared_ptr<Test> sptr2 = std::move(uptr1);

二、unique_ptr 作为继承乘次结构中对象的两个函数返回类型

  • 为什么要用智能指针?
    • 因为多态的需求,例如工厂模式
  • 为什么要用智能指针?
    • 栈上内容传不出来,堆上内存不好控制

三、智能指针的自定义删除器

// 方式1
auto delInvmt1=[](Investment* pInvestment)
               { std::cout << "delete" << std::endl;
                 delete pInvestment;}
// 方式2
void delInvmt2(Investment* pInvestment)
{ std::cout << "delete" << std::endl;
  delete pInvestment;
}

// 调用
std::unique_ptr<Investment, void(*)(Investment*)> uptr2(nullptr, delInvmt2); // 16字节
std::unique_ptr<Investment, decltype(delInvmt1)> uptr1(nullptr, delInvmt1);  // 8字节
  • 尽可能的传入lambda表达式,而不是指针
  • 具有很多状态的自定义删除器会产生大尺寸的std::unique_ptr对象。如果你发现自定义删除器使得你的std::unique_ptr 变得过大,则你需要审视修改你的设计

例子

#include <memory>
#include <iostream>

class Investment
{
public:
    virtual ~Investment() {}
};

class Stock : public Investment
{
public:
    Stock(int a) { std::cout << "Stock(int a)" << std::endl; }
    ~Stock() override { std::cout << "~Stock()" << std::endl; }
};
class Bond : public Investment
{
public:
    Bond(int a, int b) { std::cout << "Bond(int a, int b)" << std::endl; }
    ~Bond() override { std::cout << "~Bond()" << std::endl; }
};
class RealEstate : public Investment
{
public:
    RealEstate(int a, int b, int c) { std::cout << "RealEstate(int a, int b, int c)" << std::endl; }
    ~RealEstate() override { std::cout << "~RealEstate()" << std::endl; }
};

// 方式1
template <typename... Ts>
Investment *makeInvestment_test(Ts &&...params)
{
    Investment *ptr;
    constexpr int numArgs = sizeof...(params);
    if constexpr (numArgs == 1)
    {
        Stock stock(std::forward<Ts>(params)...);
        ptr = &stock;  //传不出去
    }
    if constexpr (numArgs == 2)
    {
        Bond bond(std::forward<Ts>(params)...);
        ptr = &bond;
    }
    if constexpr (numArgs == 3)
    {

        RealEstate realEstate(std::forward<Ts>(params)...);
        ptr = &realEstate;
    }
    return ptr;
}

// 方式2
template <typename... Ts>
Investment *makeInvestment_test2(Ts &&...params)
{
    Investment *ptr;
    constexpr int numArgs = sizeof...(params);
    if constexpr (numArgs == 1)
    {
        Stock *stock = new Stock(std::forward<Ts>(params)...);
        ptr = stock;
    }
    if constexpr (numArgs == 2)
    {
        Bond *bond = new Bond(std::forward<Ts>(params)...);
        ptr = bond;
    }
    if constexpr (numArgs == 3)
    {

        RealEstate *realEstate = new RealEstate(std::forward<Ts>(params)...);
        ptr = &realEstate;
    }
    return ptr;
}

// 方式3
template <typename... Ts>   // 返回指向对象的std::unique_ptr,
std::unique_ptr<Investment> // 对象使用给定实参创建
makeInvestment(Ts &&...params)
{
    std::unique_ptr<Investment> uptr{nullptr};
    constexpr int numArgs = sizeof...(params);
    if constexpr (numArgs == 1)
    {
        uptr.reset(new Stock(std::forward<Ts>(params)...));
    }
    if constexpr (numArgs == 2)
    {
        uptr.reset(new Bond(std::forward<Ts>(params)...));
    }
    if constexpr (numArgs == 3)
    {
        uptr.reset(new RealEstate(std::forward<Ts>(params)...));
    }
    return uptr;
}

auto delInvmt = [](Investment *pInvestment) // 自定义删除器
{                                           // (lambda表达式)
    std::cout << "delete" << std::endl;
    delete pInvestment;
};

// 方式4
template <typename... Ts>
std::unique_ptr<Investment, decltype(delInvmt)> // 更改后的返回类型
makeInvestment2(Ts &&...params)
{
    std::unique_ptr<Investment, decltype(delInvmt)> // 应返回的指针
        uptr(nullptr, delInvmt);
    constexpr int numArgs = sizeof...(params);
    if constexpr (numArgs == 1)
    {
        uptr.reset(new Stock(std::forward<Ts>(params)...));
    }
    if constexpr (numArgs == 2)
    {
        uptr.reset(new Bond(std::forward<Ts>(params)...));
    }
    if constexpr (numArgs == 3)
    {
        uptr.reset(new RealEstate(std::forward<Ts>(params)...));
    }
    return uptr;
}

// 方式5
template <typename... Ts>
auto makeInvestment3(Ts &&...params) // C++14
{
    auto delInvmt2 = [](Investment *pInvestment) // 现在在
    {                                            // makeInvestment里
        std::cout << "delete" << std::endl;
        delete pInvestment;
    };

    std::unique_ptr<Investment, decltype(delInvmt2)> // 应返回的指针
        uptr(nullptr, delInvmt2);
    constexpr int numArgs = sizeof...(params);
    if constexpr (numArgs == 1)
    {
        uptr.reset(new Stock(std::forward<Ts>(params)...));
    }
    if constexpr (numArgs == 2)
    {
        uptr.reset(new Bond(std::forward<Ts>(params)...));
    }
    if constexpr (numArgs == 3)
    {
        uptr.reset(new RealEstate(std::forward<Ts>(params)...));
    }
    return uptr;
}

void delInvmt3(Investment *pInvestment) // 函数形式的
{                                       // 自定义删除器
    std::cout << "delete" << std::endl;
    delete pInvestment;
}

int main()
{
    {
        Investment *ptr = makeInvestment_test(1);
        Investment *ptr2 = makeInvestment_test2(1);
        std::cout << "over";
    }
    {
        std::unique_ptr<Investment> uptrS = makeInvestment(1);
        //     auto size = sizeof(uptrS);
        //     std::unique_ptr<Investment> uptrB = makeInvestment(1, 2);
        //     std::unique_ptr<Investment> uptrR = makeInvestment(1, 2, 3);
    }
    {
        auto uptrS = makeInvestment2(1);
        //     auto size = sizeof(uptrS);
        //     std::unique_ptr<Investment, decltype(delInvmt)> uptrB = makeInvestment2(1, 2);
        //     std::unique_ptr<Investment, decltype(delInvmt)> uptrR = makeInvestment2(1, 2, 3);
    }

    // {
    //     auto uptrS = makeInvestment3(1);
    //     auto size = sizeof(uptrS);
    //     auto uptrB = makeInvestment3(1, 2);
    //     auto uptrR = makeInvestment3(1, 2, 3);
    // }

    // {
    //     std::unique_ptr<Investment, void (*)(Investment *)> uptr(nullptr, delInvmt3);
    //     std::unique_ptr<Investment, decltype(delInvmt)> uptr2(nullptr, delInvmt);
    //     auto size = sizeof(uptr);
    //     size = sizeof(uptr2);
    //     std::cout << "over";
    // }
    std::cout << "over" << std::endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值