C++ 为什么我的UniqPtr对象的大小是std::unique\u ptr的两倍?

C++ 为什么我的UniqPtr对象的大小是std::unique\u ptr的两倍?,c++,smart-pointers,unique-ptr,C++,Smart Pointers,Unique Ptr,在实际应用中,我应该坚持使用标准的图书馆设施,为了实践和理解这些设施是如何工作的,我应该尝试实现自己的设施 在这里,我实现了智能指针的模拟unique\u ptr: #include<iostream> #include <memory> template <typename T> class DefDel { public: template <typename U> void operator()(U* p)const

在实际应用中,我应该坚持使用标准的图书馆设施,为了实践和理解这些设施是如何工作的,我应该尝试实现自己的设施

在这里,我实现了智能指针的模拟
unique\u ptr

#include<iostream>
#include <memory>


template <typename T>
class DefDel
{
public:
    template <typename U>
    void operator()(U* p)const
    {
        std::cout << "freeing memory...\n";
        delete p;
    }
};

template <typename T>
class DefDel<T[]>
{
public:
    template <typename U>
    void operator()(U* p)const
    {
        std::cout << "freeing memory of an array of objects...\n";
        delete[] p;
    }
};

template <typename T, typename D = DefDel<T>>
class UniqPtr final
{
public:
    UniqPtr(T* = nullptr, D = DefDel<T>{});
    UniqPtr(UniqPtr const&) = delete;
    UniqPtr(UniqPtr&&) noexcept;
    UniqPtr& operator =(UniqPtr const&) = delete;
    UniqPtr& operator =(UniqPtr&&) noexcept;
    ~UniqPtr();
    T& operator*();
    T const& operator*() const;
    T* operator->();
    T const* operator->() const;
    operator bool() const;

private:
    T* ptr_{nullptr};
    D del_{};
};

template <typename T, typename D>
UniqPtr<T, D>::UniqPtr(T* p, D del) :
    ptr_(p),
    del_(del)
{}

template <typename T, typename D>
UniqPtr<T, D>::UniqPtr(UniqPtr&& rhs) noexcept :
    ptr_(std::move(rhs.ptr_)),
    del_(std::move(rhs.del_))
{
    rhs.ptr_ = nullptr;
}

template <typename T, typename D>
UniqPtr<T, D>& UniqPtr<T, D>::operator = (UniqPtr&& rhs) noexcept
{
    if(this != &rhs)
    {
        ptr_ = std::move(rhs.ptr_);
        del_ = std::move(rhs.del_);
        rhs.ptr_ = nullptr;
    }
    return *this;
}

template <typename T, typename D>
UniqPtr<T, D>::~UniqPtr()
{
    del_(ptr_);
}

template <typename T, typename D>
T& UniqPtr<T, D>::operator*()
{
    return *ptr_;
}

template <typename T, typename D>
T const& UniqPtr<T, D>::operator*() const
{
    return *ptr_;
}

template <typename T, typename D>
T* UniqPtr<T, D>::operator->()
{
    return ptr_;
}

template <typename T, typename D>
T const* UniqPtr<T, D>::operator->() const
{
    return ptr_;
}

template <typename T, typename D>
UniqPtr<T, D>::operator bool() const
{
    return ptr_;
}

// for array
template <typename T, typename D>
class UniqPtr<T[], D> final
{
public:
    UniqPtr(T* = nullptr, D = DefDel<T[]>{});
    UniqPtr(UniqPtr const&) = delete;
    UniqPtr(UniqPtr&&) noexcept;
    UniqPtr& operator =(UniqPtr const&) = delete;
    UniqPtr& operator =(UniqPtr&&) noexcept;
    ~UniqPtr();
    T& operator*();
    T const& operator*() const;
    T* operator->();
    T const* operator->() const;
    operator bool() const;

private:
    T* ptr_{nullptr};
    D del_{};
};

template <typename T, typename D>
UniqPtr<T[], D>::UniqPtr(T* p, D del) :
    ptr_(p),
    del_(del)
{}

template <typename T, typename D>
UniqPtr<T[], D>::UniqPtr(UniqPtr&& rhs) noexcept :
    ptr_(std::move(rhs.ptr_)),
    del_(std::move(rhs.del_))
{
    rhs.ptr_ = nullptr;
}

template <typename T, typename D>
UniqPtr<T[], D>& UniqPtr<T[], D>::operator = (UniqPtr&& rhs) noexcept
{
    if(this != &rhs)
    {
        ptr_ = std::move(rhs.ptr_);
        del_ = std::move(rhs.del_);
        rhs.ptr_ = nullptr;
    }
    return *this;
}

template <typename T, typename D>
UniqPtr<T[], D>::~UniqPtr()
{
    del_(ptr_);
}

template <typename T, typename D>
T& UniqPtr<T[], D>::operator*()
{
    return *ptr_;
}

template <typename T, typename D>
T const& UniqPtr<T[], D>::operator*() const
{
    return *ptr_;
}

template <typename T, typename D>
T* UniqPtr<T[], D>::operator->()
{
    return ptr_;
}

template <typename T, typename D>
T const* UniqPtr<T[], D>::operator->() const
{
    return ptr_;
}

template <typename T, typename D>
UniqPtr<T[], D>::operator bool() const
{
    return ptr_;
}


int main()
{

    UniqPtr<int[]> upi(new int[3]{57});
    std::cout << sizeof(upi) << '\n';
    std::unique_ptr<int[], DefDel<int[]>> upi2(new int[3]{57});
    std::cout << sizeof(upi2) << '\n';
}
#包括
#包括
模板
类定义
{
公众:
模板
void运算符()(U*p)常量
{
std::cout()常量;
运算符bool()常量;
私人:
T*ptr{nullptr};
D del_{};
};
模板
UniqPtr::UniqPtr(T*p,D del):
ptr_p,
德尔(德尔)
{}
模板
UniqPtr::UniqPtr(UniqPtr&rhs)无例外:
ptr(标准::移动(rhs.ptr)),
删除(标准::移动(右侧删除))
{
rhs.ptr u=空ptr;
}
模板
UniqPtr&UniqPtr::运算符=(UniqPtr&rhs)无例外
{
如果(此!=&rhs)
{
ptr=标准::移动(rhs.ptr);
del_uu=std::move(rhs.del_uu);
rhs.ptr u=空ptr;
}
归还*这个;
}
模板
UniqPtr::~UniqPtr()
{
del_(ptr_);
}
模板
T&UniqPtr::运算符*()
{
返回*ptr_2;;
}
模板
常量和UniqPtr::运算符*()常量
{
返回*ptr_2;;
}
模板
T*UniqPtr::运算符->()
{
返回ptr;
}
模板
常量*UniqPtr::运算符->()常量
{
返回ptr;
}
模板
UniqPtr::运算符bool()常量
{
返回ptr;
}
//用于阵列
模板
UniqPtr类期末考试
{
公众:
UniqPtr(T*=nullptr,D=DefDel{});
UniqPtr(UniqPtr const&)=删除;
UniqPtr(UniqPtr&&)无例外;
UniqPtr&运算符=(UniqPtr const&)=删除;
UniqPtr&运算符=(UniqPtr&&)无例外;
~UniqPtr();
T&算子*();
T常量&运算符*()常量;
T*运算符->();
T常量*运算符->()常量;
运算符bool()常量;
私人:
T*ptr{nullptr};
D del_{};
};
模板
UniqPtr::UniqPtr(T*p,D del):
ptr_p,
德尔(德尔)
{}
模板
UniqPtr::UniqPtr(UniqPtr&rhs)无例外:
ptr(标准::移动(rhs.ptr)),
删除(标准::移动(右侧删除))
{
rhs.ptr u=空ptr;
}
模板
UniqPtr&UniqPtr::运算符=(UniqPtr&rhs)无例外
{
如果(此!=&rhs)
{
ptr=标准::移动(rhs.ptr);
del_uu=std::move(rhs.del_uu);
rhs.ptr u=空ptr;
}
归还*这个;
}
模板
UniqPtr::~UniqPtr()
{
del_(ptr_);
}
模板
T&UniqPtr::运算符*()
{
返回*ptr_2;;
}
模板
常量和UniqPtr::运算符*()常量
{
返回*ptr_2;;
}
模板
T*UniqPtr::运算符->()
{
返回ptr;
}
模板
常量*UniqPtr::运算符->()常量
{
返回ptr;
}
模板
UniqPtr::运算符bool()常量
{
返回ptr;
}
int main()
{
UniqPtr upi(新国际[3]{57});
标准::cout
为什么我的UniqPtr对象的大小是std::unique\u ptr的两倍(即使使用相同的值初始化)?
这是因为我的类将Del_uu对象存储为成员吗

对。 因为
D del_
需要存储,并且每个
T*ptr_
必须正确对齐

如果这就是问题所在,那么我如何以0成本实现与unique_ptr非常相似的行为

您可以私下从
D
派生,而不是让它成为成员。这样,带有空类的实例化就不会占用额外的存储空间

template <typename T, typename D = DefDel<T>>
class UniqPtr final : D
{
public:
    UniqPtr(T* = nullptr, D = {});
    UniqPtr(UniqPtr const&) = delete;
    UniqPtr(UniqPtr&&) noexcept;
    UniqPtr& operator =(UniqPtr const&) = delete;
    UniqPtr& operator =(UniqPtr&&) noexcept;
    ~UniqPtr();
    T& operator*();
    T const& operator*() const;
    T* operator->();
    T const* operator->() const;
    operator bool() const;

private:
    T* ptr_{nullptr};
};

template <typename T, typename D>
UniqPtr<T, D>::UniqPtr(T* p, D del) :
    D(del),
    ptr_(p)
{}

template <typename T, typename D>
UniqPtr<T, D>::UniqPtr(UniqPtr&& rhs) noexcept :
    D(std::move(*rhs)),
    ptr_(std::exchange(rhs.ptr_, nullptr))
{}

template <typename T, typename D>
UniqPtr<T, D>& UniqPtr<T, D>::operator = (UniqPtr&& rhs) noexcept
{
    using std::swap;
    swap(static_cast<D&>(*this), static_cast<D&>(rhs));
    swap(ptr_, rhs.ptr_);
}

template <typename T, typename D>
UniqPtr<T, D>::~UniqPtr()
{
    static_cast<D&>(*this)(ptr_);
}
模板
UniqPtr类期末考试:D
{
公众:
UniqPtr(T*=nullptr,D={});
UniqPtr(UniqPtr const&)=删除;
UniqPtr(UniqPtr&&)无例外;
UniqPtr&运算符=(UniqPtr const&)=删除;
UniqPtr&运算符=(UniqPtr&&)无例外;
~UniqPtr();
T&算子*();
T常量&运算符*()常量;
T*运算符->();
T常量*运算符->()常量;
运算符bool()常量;
私人:
T*ptr{nullptr};
};
模板
UniqPtr::UniqPtr(T*p,D del):
D(del),
ptr_uP
{}
模板
UniqPtr::UniqPtr(UniqPtr&rhs)无例外:
D(标准:移动(*rhs)),
ptr_(std::exchange(rhs.ptr_,nullptr))
{}
模板
UniqPtr&UniqPtr::运算符=(UniqPtr&rhs)无例外
{
使用std::swap;
交换(静态_-cast(*本),静态_-cast(rhs));
交换(ptr_u2;,rhs.ptr_2;);
}
模板
UniqPtr::~UniqPtr()
{
静态铸件(*本)(ptr);
}

为什么不能使用调试器同时检查对象和示例
unique_ptr
实例,比较它们的内部布局,看看差异在哪里?这是你应该能够自己确定的,毕竟这是调试器的目的之一。@SamVarshavchik:你认为我的上课有点好?我不知道什么是“好”意思是,这是一个模板类。我看不出任何一个不好的东西。如果它对C++编译器足够好,对我来说就足够了。”SamVarshavchik:谢谢。我的意思是,它里面有一些错误或错误。我看到的唯一的设计问题就是让DELTER类作为一个类成员完全没有任何用处。l、 除此之外,您可能认为这会使类的大小变大。唯一类中需要引用删除器代码的任何代码都可以简单地引用类本身,而删除器类本身可以是一个普通的模板函数。谢谢。请添加一些建议的代码好吗?