一、默认情况下 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;
}