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