欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > 条款18:对独占资源使用std::unique_ptr

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

2025/4/21 1:15:46 来源:https://blog.csdn.net/qq_40178082/article/details/144788379  浏览:    关键词:条款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;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词